USER ID: примеры (SQL)
USER_ID([ 'user' ]): intОсновные сведения о функции USER_ID
Функция USER_ID в Microsoft SQL Server возвращает идентификационный номер (ID) пользователя базы данных. Этот идентификатор является целым числом (тип int) и уникален в пределах конкретной базы данных. Функция существует в первую очередь для обеспечения обратной совместимости. В новых разработках рекомендуется использовать более современные системные представления, такие как sys.database_principals.
Синтаксис: USER_ID ( [ 'user' ] )
Аргументы:
'user'(необязательный): Имя пользователя базы данных, для которого требуется получить идентификатор. Аргумент имеет типsysname. Если аргумент не указан, функция возвращает ID текущего пользователя.
Возвращаемое значение: Функция возвращает значение типа int.
- Если указано имя существующего пользователя базы данных, возвращается его ID.
- Если аргумент не указан, возвращается ID текущего пользователя.
- Если указано имя несуществующего пользователя или имя пользователя Windows, не имеющего соответствующего пользователя в базе данных, функция возвращает
NULL. - Для встроенных ролей базы данных (таких как
dbo,guest) также возвращаются их идентификаторы.
Функция находит применение в сценариях, где необходимо программно определить или сравнить идентификаторы пользователей для управления доступом, аудита или логирования действий.
Простые примеры использования
Пример 1: Получение ID текущего пользователя.
SELECT USER_ID() AS CurrentUserID;CurrentUserID --------------- 5
Пример 2: Получение ID конкретного пользователя базы данных.
SELECT USER_ID('dbo') AS DboUserID, USER_ID('guest') AS GuestUserID;DboUserID GuestUserID --------- ----------- 1 2
Пример 3: Попытка получить ID несуществующего пользователя.
SELECT USER_ID('NonExistentUser') AS ID_For_Unknown;ID_For_Unknown --------------- NULL
Аналогичные функции в MS SQL Server
- DATABASE_PRINCIPAL_ID('principal_name'): Более современная и предпочтительная функция. Работает аналогично USER_ID, но поддерживает все типы участников базы данных (пользователи, роли, группы приложений), а не только пользователей. Рекомендуется для использования в новых разработках.
- SUSER_ID('login'): Возвращает идентификационный номер имени входа на уровне экземпляра SQL Server (сервера), а не на уровне базы данных.
- SYSTEM_USER: Возвращает имя текущего пользователя, а не его ID.
- CURRENT_USER: Возвращает имя текущего пользователя (соответствует стандарту SQL).
- sys.database_principals: Системное представление, которое содержит все сведения об участниках базы данных, включая их имена (
name) и идентификаторы (principal_id). Это наиболее гибкий способ получения информации. Например:SELECT principal_id FROM sys.database_principals WHERE name = 'username';
Аналоги в других СУБД
- PostgreSQL: Используется функция
pg_user.usesysidв сочетании с системным представлением. Самостоятельной функции USER_ID нет.SELECT usesysid FROM pg_user WHERE usename = CURRENT_USER; - Oracle: Аналогом можно считать столбец
USER_IDв представленииDBA_USERSилиALL_USERS.SELECT user_id FROM dba_users WHERE username = USER; - MySQL: Прямого аналога нет. Идентификатор пользователя не является стандартным понятием в этой модели. Для получения информации о пользователе используют системные представления, такие как
mysql.user. - SQLite: Концепция пользовательских ID в базе данных отсутствует.
Типичные ошибки и особенности
1. Путаница между пользователем базы данных и именем входа на сервер. Функция USER_ID работает только с пользователями базы данных. Передача имени входа Windows или SQL Server Authentication, для которого нет соответствующего пользователя в текущей базе, вернет NULL.
-- Если 'SomeLogin' является именем входа, но не пользователем в этой БД:
SELECT USER_ID('SomeLogin'); -- Вернет NULL2. Ожидание, что функция всегда вернет не-NULL значение для существующего пользователя. Для встроенных системных пользователей или ролей функция возвращает их ID.
3. Использование функции для проверки существования пользователя. Лучше использовать представление sys.database_principals.
-- Ненадежный способ:
IF USER_ID('SomeUser') IS NOT NULL PRINT 'User exists';
-- Более надежный способ:
IF EXISTS (SELECT 1 FROM sys.database_principals WHERE name = 'SomeUser') PRINT 'User exists';История изменений
Функция USER ID не претерпела значительных синтаксических изменений в последних версиях SQL Server. Основное изменение связано с философией использования. Начиная с SQL Server 2005 и более поздних версий, корпорация Microsoft рекомендует для новых разработок использовать представления совместимости каталогов (sys.*), а не функции, подобные USER_ID. Сама функция сохранена для обеспечения обратной совместимости со старыми версиями и скриптами.
Расширенные примеры применения
Пример 1: Использование в выражении CASE для определения уровня доступа.
SELECT
CASE USER_ID()
WHEN USER_ID('dbo') THEN 'Полный доступ (владелец базы данных)'
WHEN USER_ID('report_user') THEN 'Доступ только для чтения отчетов'
ELSE 'Стандартный доступ'
END AS AccessLevel;AccessLevel --------------------------------- Полный доступ (владелец базы данных)
Пример 2: Логирование действий с сохранением ID пользователя.
CREATE TABLE dbo.AuditLog (
LogID int IDENTITY PRIMARY KEY,
ActionTime datetime DEFAULT GETDATE(),
UserDB_ID int,
ActionDescription nvarchar(255)
);
-- Вставка записи в журнал аудита
INSERT INTO dbo.AuditLog (UserDB_ID, ActionDescription)
VALUES (USER_ID(), 'Запущена процедура генерации отчета');
-- Просмотр журнала с именем пользователя
SELECT
al.ActionTime,
dp.name AS UserName,
al.ActionDescription
FROM dbo.AuditLog al
LEFT JOIN sys.database_principals dp ON al.UserDB_ID = dp.principal_id;Пример 3: Сравнение идентификаторов для условного выполнения кода в хранимой процедуре.
IF USER_ID() = USER_ID('service_account')
BEGIN
PRINT 'Выполняется автоматическая задача обслуживания.';
-- Код специальной логики
END
ELSE
BEGIN
PRINT 'Выполняется задача, инициированная пользователем.';
-- Стандартная логика
ENDПример 4: Создание динамического SQL с учетом пользователя (с осторожностью).
DECLARE @DynamicSQL nvarchar(MAX);
DECLARE @SchemaName sysname;
-- Предположим, что схема пользователя совпадает с его именем
SELECT @SchemaName = name FROM sys.database_principals WHERE principal_id = USER_ID();
SET @DynamicSQL = N'SELECT COUNT(*) FROM ' + QUOTENAME(@SchemaName) + N'.SomeTable';
-- EXEC sp_executesql @DynamicSQL;
PRINT @DynamicSQL;