HAS PERMS BY NAME: примеры (SQL)
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. Рекомендуется обращаться к документации по конкретной версии сервера.
Расширенные примеры
Динамическое формирование запроса в зависимости от прав пользователя.
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Проверка возможности выполнения действия перед попыткой его совершения в хранимой процедуре.
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;Массовая проверка прав на все таблицы в схеме.
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
Использование с подзапросом для проверки прав на объект, имя которого хранится в таблице.
SELECT
ObjectName,
HAS_PERMS_BY_NAME(ObjectName, 'OBJECT', 'UPDATE') AS CanUpdate
FROM dbo.AuditList;