2013-08-12 9 views
9

Я ищу оператор выбора, который будет извлекать список всех ролей базы данных для моего текущего соединения.Как запросить роли текущего пользователя

Я хочу, чтобы создать представление, которое будет возвращать все роли в клиентское программное обеспечение, такое, что программное обеспечение может настроить свой пользовательский интерфейс в соответствии с ролями (например показать/скрыть пункты меню и т.д.)

ответ

17

Вы не должны использовать устаревшие отсталые взгляды на совместимость (search this page for sysusers, for example). Вместо этого вы должны использовать sys.database_principals и sys.database_role_members. Имейте в виду, что текущему соединению может быть предоставлен доступ за пределами области действия базы данных (например, они возвратят пустые результаты, если пользователь окажется sysadmin, и в этом случае им не нужно явно предоставлять членство в роли или конкретное разрешения). Кроме того, для разрешений, явно назначенных за пределами роли роли, которая будет переопределять функции, предоставленные этой ролью, вы должны дополнительно проверить sys.database_permissions. Вот автономный пример, который вы можете проверить (если у вас еще нет логина с именем blatfarA или базы данных под названием floob).

CREATE LOGIN blatfarA WITH PASSWORD = 'foo', CHECK_POLICY = OFF; 
GO 
CREATE DATABASE floob; 
GO 
USE floob; 
GO 
CREATE USER blatfarB FROM LOGIN [blatfarA] WITH DEFAULT_SCHEMA = dbo; 
GO 
GRANT SELECT, UPDATE ON SCHEMA::dbo TO blatfarB; 
DENY INSERT, EXECUTE ON SCHEMA::dbo TO blatfarB; 
GO 
EXEC sp_addrolemember N'db_datareader', N'blatfarB' 
GO 

Чтобы проверить:

EXECUTE AS LOGIN = N'blatfarA'; 
GO 

DECLARE @login NVARCHAR(256), @user NVARCHAR(256); 

SELECT @login = login_name FROM sys.dm_exec_sessions WHERE session_id = @@SPID; 

SELECT @user = d.name 
    FROM sys.database_principals AS d 
    INNER JOIN sys.server_principals AS s 
    ON d.sid = s.sid 
    WHERE s.name = @login; 

SELECT u.name, r.name 
    FROM sys.database_role_members AS m 
    INNER JOIN sys.database_principals AS r 
    ON m.role_principal_id = r.principal_id 
    INNER JOIN sys.database_principals AS u 
    ON u.principal_id = m.member_principal_id 
    WHERE u.name = @user; 

SELECT class_desc, major_id, permission_name, state_desc 
    FROM sys.database_permissions 
    WHERE grantee_principal_id = USER_ID(@user); 

GO 
REVERT; 

Результаты:

name  name 
-------- ------------- 
blatfarB db_datareader 

class_desc major_id permission_name state_desc 
---------- -------- --------------- ---------- 
DATABASE 0   CONNECT   GRANT 
SCHEMA  1   INSERT   DENY 
SCHEMA  1   EXECUTE   DENY 
SCHEMA  1   SELECT   GRANT 
SCHEMA  1   UPDATE   GRANT 

ВЫМЫТЬ:

USE master; 
GO 
ALTER DATABASE floob SET SINGLE_USER WITH ROLLBACK IMMEDIATE; 
GO 
DROP DATABASE floob; 
GO 
DROP LOGIN blatfarA; 
GO 
+0

Эй, спасибо, это намного лучше. Между тем, я обнаружил, что моя первая попытка не всегда давала правильные результаты. Я изменил принятый ответ. –

+1

Возможно, вы упростите код в демо, чтобы использовать 'CURRENT_USER' вместо того, чтобы беспокоиться о запросе' @ login'. Старые привычки умирают с трудом. –

+0

«Старые привычки умереть» - вы очень правы! –

5

здесь, где вы можете Старт:

select u.name, g.name 
from sysmembers as m 
    inner join sys.sysusers u on u.[uid] = m.memberuid 
    inner join sys.sysusers g on g.[uid] = m.groupuid 
+2

Почему вы используете устаревшие виды совместимости, которые будут удалены в будущем версия SQL Server? (Search [this page] (http://technet.microsoft.com/en-us/library/bb510662 (v = sql.100) .aspx) для 'sysusers'.) –

+0

Кроме того, я не вижу, как это ответы «Я хочу знать все DATABASE ROLES, которые были назначены моему текущему соединению». Это возвращает все. –

Смежные вопросы