USER NAME: примеры (SQL)

Использование функции USER_NAME в Microsoft SQL Server
Раздел: Функции безопасности и шифрования, Безопасность
USER_NAME([id]): nvarchar(128)

Функция USER_NAME в MS SQL Server

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

Основное назначение функции — преобразование идентификатора пользователя базы данных (principal_id) в его символьное имя. Это полезно при аудите, отладке и формировании отчетов, когда в системных таблицах или представлениях хранятся числовые идентификаторы, но для восприятия требуются читаемые имена.

Синтаксис функции:

USER_NAME ( [ id ] )

Аргументы:

  • id (необязательный) — идентификационный номер пользователя базы данных (principal_id) типа int. Если аргумент не указан, функция возвращает имя текущего пользователя.

Возвращаемое значение:

  • Тип данных nvarchar(128).
  • Если указан существующий id, возвращается имя пользователя, связанное с этим идентификатором.
  • Если указан NULL или аргумент опущен, возвращается имя текущего пользователя базы данных.
  • Если указан несуществующий числовой id, функция возвращает NULL.

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

Возврат имени текущего пользователя:

SELECT USER_NAME() AS CurrentUserName;
CurrentUserName
dbo

Возврат имени пользователя по известному идентификатору (например, 1):

SELECT USER_NAME(1) AS UserNameById;
UserNameById
dbo

Использование с аргументом NULL:

SELECT USER_NAME(NULL) AS UserNameNull;
UserNameNull
dbo

Попытка получить имя для несуществующего идентификатора:

SELECT USER_NAME(999999) AS NonExistentUser;
NonExistentUser
NULL

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

  • SUSER_NAME([server_user_id]) — возвращает имя входа на уровне экземпляра сервера. Применяется, когда требуется информация об имени входа SQL Server или Windows, а не о пользователе базы данных.
  • SYSTEM_USER — функция без аргументов, возвращающая имя входа текущего контекста безопасности на уровне сервера. Это аналогично SUSER_NAME() без параметра.
  • CURRENT_USER — функция без аргументов, возвращающая имя текущего пользователя базы данных. Поведение идентично USER_NAME() без параметра, но соответствует стандарту SQL.
  • ORIGINAL_LOGIN() — возвращает имя входа, с которым пользователь изначально подключился к экземпляру. Полезна для аудита в сценариях олицетворения (EXECUTE AS).

Выбор функции зависит от контекста: USER_NAME() работает на уровне базы данных, SUSER_NAME() и SYSTEM_USER — на уровне сервера. CURRENT_USER предпочтительнее для кросс-платформенной совместимости.

Аналоги функции в других СУБД

MySQL: Функция USER() возвращает имя пользователя и хост для текущего сеанса. Аналогом USER_NAME(id) в чистом виде нет.

SELECT USER();
'root@localhost'

Oracle: Псевдостолбец USER возвращает имя текущего пользователя. Для получения имени по ID можно запросить системное представление ALL_USERS.

SELECT USER FROM DUAL;
SYSTEM

PostgreSQL: Функция current_user возвращает имя текущего пользователя. Информация о пользователях доступна в представлении pg_user.

SELECT current_user;
postgres

SQLite: Концепция пользователей базы данных отсутствует. Управление доступом обычно осуществляется на уровне файловой системы.

Sybase ASE: Функция USER_NAME([uid]) аналогична по синтаксису и поведению MS SQL Server.

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

Передача нечислового аргумента приводит к ошибке преобразования типов:

SELECT USER_NAME('admin');
Msg 8114, Level 16, State 5, Line 1
Error converting data type varchar to int.

Ожидание возврата имени пользователя для идентификатора, относящегося к роли, а не к пользователю. Роли также являются участниками (principals), но USER_NAME для них возвращает NULL:

-- Пытаемся получить имя для идентификатора роли 'public' (обычно 0)
SELECT USER_NAME(0);
NULL

Использование функции для идентификаторов участников уровня сервера (логинов). USER_NAME работает только с пользователями базы данных:

-- ID 1 в базе данных может быть пользователем 'dbo',
-- а на сервере — логином 'sa'. Это разные сущности.
-- Следующий запрос вернет имя пользователя БД, а не логина.
SELECT USER_NAME(1);

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

В актуальных версиях Microsoft SQL Server (2016 и новее) значительных изменений в поведении или синтаксисе функции USER NAME не было. Функция сохраняет обратную совместимость с предыдущими версиями.

Отмечается, что возвращаемый тип данных nvarchar(128) остался неизменным, несмотря на то что в SQL Server 2012 и выше максимальная длина имен участников может достигать 128 символов (в более старых версиях — 256 для SQL Server 2000).

Расширенные примеры использования

Сопоставление идентификаторов пользователей с их именами в системном представлении sys.database_principals:

Пример sql
SELECT principal_id, name, type_desc,
       USER_NAME(principal_id) AS NameViaFunction
FROM sys.database_principals
WHERE type IN ('S', 'U', 'G') -- SQL пользователь, пользователь Windows, группа Windows
ORDER BY principal_id;
principal_id  name       type_desc               NameViaFunction
1            dbo        SQL_USER                dbo
3            guest      SQL_USER                guest
4            INFORMATIKA\User1 WINDOWS_USER    INFORMATIKA\User1

Использование в триггере для аудита изменений с сохранением имени пользователя:

Пример sql
CREATE TABLE dbo.EmployeeAudit (
    AuditID INT IDENTITY PRIMARY KEY,
    EmployeeID INT NOT NULL,
    ChangedBy NVARCHAR(128) DEFAULT USER_NAME(),
    ChangeTime DATETIME DEFAULT GETDATE(),
    Action CHAR(1)
);

Определение владельца объекта в базе данных:

Пример sql
SELECT OBJECT_NAME(object_id) AS ObjectName,
       USER_NAME(principal_id) AS OwnerName
FROM sys.objects
WHERE principal_id IS NOT NULL;

Использование в динамическом SQL для построения запроса с учетом текущего пользователя:

Пример sql
DECLARE @CurrentUser NVARCHAR(128) = USER_NAME();
DECLARE @SQL NVARCHAR(MAX);
SET @SQL = N'SELECT * FROM dbo.SensitiveData WHERE Responsible = ''' + @CurrentUser + ''''; 
EXEC sp_executesql @SQL;

Сравнение текущего пользователя с владельцем схемы:

Пример sql
IF USER_NAME() <> SCHEMA_NAME()
    PRINT 'Текущий пользователь не является владельцем схемы по умолчанию.';

MS SQL USER_NAME function comments

En
USER NAME Returns a database user name from a specified identification number