HAS PERMS BY NAME: примеры (SQL)

Проверка прав доступа с помощью HAS_PERMS_BY_NAME в SQL Server
Раздел: Функции управления системой
HAS_PERMS_BY_NAME( 'securable' , 'securable_class' , 'permission' [ , 'sub-securable' ] [ , 'sub-securable_class' ] ): int

Функция HAS_PERMS_BY_NAME

Функция HAS_PERMS_BY_NAME в Microsoft SQL Server предназначена для проверки наличия определенного разрешения у текущего пользователя на заданный защищаемый объект. Эта функция используется в сценариях управления доступом, при динамическом формировании запросов или для создания гибких механизмов аудита прав.

Функция возвращает целочисленное значение: 1 — если разрешение есть, 0 — если разрешения нет, и NULL — если входные параметры недопустимы или произошла ошибка при оценке.

Аргументы функции:

  • securable (опционально): Имя защищаемого объекта (например, 'MyTable', 'MyDatabase'). Может быть NULL.
  • securable_class (опционально): Класс объекта. Например: 'OBJECT', 'DATABASE', 'SCHEMA', 'ROLE'.
  • permission (обязательно): Имя проверяемого разрешения (например, 'SELECT', 'INSERT', 'CONTROL').
  • sub-securable (опционально): Идентификатор вложенного объекта (например, имя столбца).
  • sub-securable_class (опционально): Класс вложенного объекта (например, 'COLUMN').

Простые примеры использования

Проверка разрешения SELECT на таблицу в текущей базе данных.

SELECT HAS_PERMS_BY_NAME('dbo.Products', 'OBJECT', 'SELECT') AS HasSelectPerm;
HasSelectPerm
1

Проверка разрешения CONTROL на всю базу данных.

SELECT HAS_PERMS_BY_NAME(NULL, 'DATABASE', 'CONTROL') AS HasDBCtrl;
HasDBCtrl
0

Проверка разрешения UPDATE на конкретный столбец таблицы.

SELECT HAS_PERMS_BY_NAME('dbo.Products', 'OBJECT', 'UPDATE', 'ProductName', 'COLUMN') AS HasColumnUpdatePerm;
HasColumnUpdatePerm
1

Проверка разрешения IMPERSONATE на пользователя.

SELECT HAS_PERMS_BY_NAME('AppUser', 'USER', 'IMPERSONATE') AS CanImpersonate;
CanImpersonate
0

Похожие функции в MS SQL Server

fn_my_permissions: Возвращает таблицу с перечнем всех разрешений текущего пользователя на заданный объект. Полезна для получения полного списка прав, а не проверки одного конкретного.

IS_MEMBER и IS_ROLEMEMBER: Проверяют членство текущего пользователя в группе Windows или роли сервера/базы данных. Не проверяют конкретные разрешения на объекты.

HAS_DBACCESS: Проверяет, есть ли у пользователя доступ к указанной базе данных. Узкоспециализированная функция для проверки доступа к БД.

Функцию HAS_PERMS_BY_NAME предпочтительнее использовать для точечной проверки конкретных прав на конкретный объект в логике приложения или скриптов. Функцию fn_my_permissions применяют для аудита или отладки, когда нужен полный список доступных действий.

Аналоги в других СУБД и языках

PostgreSQL: Используются функции вида has_table_privilege(), has_column_privilege(). Проверка происходит для текущего пользователя или указанного ролевого.

SELECT has_table_privilege('public.products', 'select');
has_table_privilege
t

Oracle: Запросы к представлениям словаря данных, например USER_TAB_PRIVS. Прямого аналога нет, проверка осуществляется через SELECT.

SELECT COUNT(*) FROM USER_TAB_PRIVS WHERE TABLE_NAME = 'EMPLOYEES' AND PRIVILEGE = 'SELECT';
COUNT(*)
1

MySQL: Функция has_table_privilege отсутствует. Проверка прав выполняется через запрос к таблице information_schema.user_privileges или с помощью команды SHOW GRANTS.

Ключевое отличие MS SQL функции — ее универсальность, так как один вызов может проверять права на объекты разных классов (от столбца до сервера). В других системах часто требуются отдельные функции или сложные запросы для каждого типа объекта.

Типичные ошибки

Некорректное имя класса объекта: Указание несуществующего класса приводит к возврату NULL.

SELECT HAS_PERMS_BY_NAME('MyTable', 'TABEL', 'SELECT') AS Result;
Result
NULL

Несоответствие класса объекта и его имени: Попытка проверить разрешение 'SELECT' для класса 'DATABASE' без указания имени объекта может дать неожиданный результат, так как проверяется разрешение на уровне базы данных, а не на конкретную таблицу.

SELECT HAS_PERMS_BY_NAME('MyTable', 'DATABASE', 'SELECT') AS Result;
Result
0

Использование для объектов в других базах данных без трехкомпонентного имени: По умолчанию функция проверяет объекты в контексте текущей базы данных. Для проверки объекта в другой БД необходимо использовать трехкомпонентное имя.

-- Текущая БД - MyDB1, нужна проверка в MyDB2
SELECT HAS_PERMS_BY_NAME('MyDB2.dbo.Orders', 'OBJECT', 'SELECT') AS Result;

Изменения в последних версиях

В документации Microsoft SQL Server 2016 и более поздних версий существенных изменений в синтаксисе или поведении функции HAS_PERMS_BY_NAME не зафиксировано. Однако, с выходом новых версий могут добавляться новые значения для аргументов securable_class и permission, соответствующие новым типам объектов и разрешений в системе безопасности SQL Server. Рекомендуется обращаться к документации по конкретной версии сервера.

Расширенные примеры

Динамическое формирование запроса в зависимости от прав пользователя.

Пример sql
DECLARE @SQL NVARCHAR(MAX);
IF HAS_PERMS_BY_NAME('SalesData', 'SCHEMA', 'SELECT') = 1
BEGIN
    SET @SQL = 'SELECT * FROM SalesData.Orders';
    EXEC sp_executesql @SQL;
END
ELSE
BEGIN
    PRINT 'Доступ запрещен';
END

Проверка возможности выполнения действия перед попыткой его совершения в хранимой процедуре.

Пример sql
CREATE PROCEDURE dbo.TryDeleteProduct @ProductID INT
AS
BEGIN
    IF HAS_PERMS_BY_NAME('dbo.Products', 'OBJECT', 'DELETE') = 0
    BEGIN
        RAISERROR('Недостаточно прав для удаления', 16, 1);
        RETURN;
    END
    DELETE FROM dbo.Products WHERE ProductID = @ProductID;
END;

Массовая проверка прав на все таблицы в схеме.

Пример sql
SELECT 
    t.name AS TableName,
    HAS_PERMS_BY_NAME('dbo.' + t.name, 'OBJECT', 'SELECT') AS CanSelect,
    HAS_PERMS_BY_NAME('dbo.' + t.name, 'OBJECT', 'INSERT') AS CanInsert
FROM sys.tables t
WHERE t.schema_id = SCHEMA_ID('dbo');
TableName    CanSelect    CanInsert
Products     1            0
Orders       1            1
Customers    1            0

Использование с подзапросом для проверки прав на объект, имя которого хранится в таблице.

Пример sql
SELECT 
    ObjectName,
    HAS_PERMS_BY_NAME(ObjectName, 'OBJECT', 'UPDATE') AS CanUpdate
FROM dbo.AuditList;

MS SQL HAS_PERMS_BY_NAME function comments

En
HAS PERMS BY NAME Evaluates the effective permission of the current user on a securable