【发布时间】:2016-09-23 06:48:44
【问题描述】:
我正在尝试审核整个服务器上的数据库权限。我有一个查询可以产生我想要的输出,但我需要针对所有数据库运行它。
大多数解决方案似乎都使用以下内容:
DECLARE @command varchar(1000)
SELECT @command = 'USE ?; SQL QUERY HERE'
EXEC sp_MSforeachdb @command
但是,这会失败并出现错误,当我自己在数据库上运行查询时不会发生这种错误。我认为这与存储在变量中有关,但使用这种格式也会失败:
EXECUTE sp_MSForEachDB
'USE ?; SQL QUERY HERE'
我尝试运行的完整查询是:
SELECT
ServerName = @@SERVERNAME,
LoginName = AccessSummary.LoginName,
LoginType = CASE WHEN syslogins.isntuser = 1 THEN 'WINDOWS_LOGIN' WHEN syslogins.isntgroup = 1 THEN 'WINDOWS_GROUP' ELSE 'SQL_USER' END,
DatabaseName = DB_NAME(),
SelectAccess = MAX(AccessSummary.SelectAccess),
InsertAccess = MAX(AccessSummary.InsertAccess),
UpdateAccess = MAX(AccessSummary.UpdateAccess),
DeleteAccess = MAX(AccessSummary.DeleteAccess),
DBOAccess = MAX(AccessSummary.DBOAccess),
SysadminAccess = MAX(AccessSummary.SysadminAccess)
FROM
(
/* Get logins with permissions */
SELECT
LoginName = sysDatabasePrincipal.name,
SelectAccess = CASE WHEN permission_name = 'SELECT' THEN 1 ELSE 0 END,
InsertAccess = CASE WHEN permission_name = 'INSERT' THEN 1 ELSE 0 END,
UpdateAccess = CASE WHEN permission_name = 'UPDATE' THEN 1 ELSE 0 END,
DeleteAccess = CASE WHEN permission_name = 'DELETE' THEN 1 ELSE 0 END,
DBOAccess = 0,
SysadminAccess = 0
FROM sys.database_permissions AS sysDatabasePermission
INNER JOIN sys.database_principals AS sysDatabasePrincipal
ON sysDatabasePrincipal.principal_id = sysDatabasePermission.grantee_principal_id
INNER JOIN sys.server_principals AS sysServerPrincipal
ON sysServerPrincipal.sid = sysDatabasePrincipal.sid
WHERE sysDatabasePermission.class_desc = 'OBJECT_OR_COLUMN'
AND sysDatabasePrincipal.type_desc IN ('WINDOWS_LOGIN', 'WINDOWS_GROUP', 'SQL_USER')
AND sysServerPrincipal.is_disabled = 0
UNION ALL
/* Get group members with permissions */
SELECT
LoginName = sysDatabasePrincipalMember.name,
SelectAccess = CASE WHEN permission_name = 'SELECT' THEN 1 ELSE 0 END,
InsertAccess = CASE WHEN permission_name = 'INSERT' THEN 1 ELSE 0 END,
UpdateAccess = CASE WHEN permission_name = 'UPDATE' THEN 1 ELSE 0 END,
DeleteAccess = CASE WHEN permission_name = 'DELETE' THEN 1 ELSE 0 END,
DBOAccess = 0,
SysadminAccess = 0
FROM sys.database_permissions AS sysDatabasePermission
INNER JOIN sys.database_principals AS sysDatabasePrincipalRole
ON sysDatabasePrincipalRole.principal_id = sysDatabasePermission.grantee_principal_id
INNER JOIN sys.database_role_members AS sysDatabaseRoleMember
ON sysDatabaseRoleMember.role_principal_id = sysDatabasePrincipalRole.principal_id
INNER JOIN sys.database_principals AS sysDatabasePrincipalMember
ON sysDatabasePrincipalMember.principal_id = sysDatabaseRoleMember.member_principal_id
INNER JOIN sys.server_principals AS sysServerPrincipal
ON sysServerPrincipal.sid = sysDatabasePrincipalMember.sid
WHERE sysDatabasePermission.class_desc = 'OBJECT_OR_COLUMN'
AND sysDatabasePrincipalRole.type_desc = 'DATABASE_ROLE'
AND sysDatabasePrincipalRole.name <> 'public'
AND sysDatabasePrincipalMember.type_desc IN ('WINDOWS_LOGIN', 'WINDOWS_GROUP', 'SQL_USER')
AND sysServerPrincipal.is_disabled = 0
UNION ALL
/* Get users in db_owner, db_datareader and db_datawriter */
SELECT
LoginName = sysServerPrincipal.name,
SelectAccess = CASE WHEN sysDatabasePrincipalRole.name IN ('db_owner', 'db_datareader') THEN 1 ELSE 0 END,
InsertAccess = CASE WHEN sysDatabasePrincipalRole.name IN ('db_owner', 'db_datawriter') THEN 1 ELSE 0 END,
UpdateAccess = CASE WHEN sysDatabasePrincipalRole.name IN ('db_owner', 'db_datawriter') THEN 1 ELSE 0 END,
DeleteAccess = CASE WHEN sysDatabasePrincipalRole.name IN ('db_owner', 'db_datawriter') THEN 1 ELSE 0 END,
DBOAccess = CASE WHEN sysDatabasePrincipalRole.name = 'db_owner' THEN 1 ELSE 0 END,
SysadminAccess = 0
FROM sys.database_principals AS sysDatabasePrincipalRole
INNER JOIN sys.database_role_members AS sysDatabaseRoleMember
ON sysDatabaseRoleMember.role_principal_id = sysDatabasePrincipalRole.principal_id
INNER JOIN sys.database_principals AS sysDatabasePrincipalMember
ON sysDatabasePrincipalMember.principal_id = sysDatabaseRoleMember.member_principal_id
INNER JOIN sys.server_principals AS sysServerPrincipal
ON sysServerPrincipal.sid = sysDatabasePrincipalMember.sid
WHERE sysDatabasePrincipalRole.name IN ('db_owner', 'db_datareader', 'db_datawriter')
AND sysServerPrincipal.type_desc IN ('WINDOWS_LOGIN', 'WINDOWS_GROUP', 'SQL_LOGIN')
AND sysServerPrincipal.is_disabled = 0
UNION ALL
/* Get users in sysadmin */
SELECT
LoginName = sysServerPrincipalMember.name,
SelectAccess = 1,
InsertAccess = 1,
UpdateAccess = 1,
DeleteAccess = 1,
DBOAccess = 0,
SysadminAccess = 1
FROM sys.server_principals AS sysServerPrincipalRole
INNER JOIN sys.server_role_members AS sysServerRoleMember
ON sysServerRoleMember.role_principal_id = sysServerPrincipalRole.principal_id
INNER JOIN sys.server_principals AS sysServerPrincipalMember
ON sysServerPrincipalMember.principal_id = sysServerRoleMember.member_principal_id
WHERE sysServerPrincipalMember.type_desc IN ('WINDOWS_LOGIN', 'WINDOWS_GROUP', 'SQL_LOGIN')
AND sysServerPrincipalMember.is_disabled = 0
) AS AccessSummary
INNER JOIN MASTER.dbo.syslogins AS syslogins
ON syslogins.loginname = AccessSummary.LoginName
WHERE AccessSummary.LoginName NOT IN ('NT SERVICE\MSSQLSERVER', 'NT AUTHORITY\SYSTEM', 'NT SERVICE\SQLSERVERAGENT')
GROUP BY
AccessSummary.LoginName,
CASE WHEN syslogins.isntuser = 1 THEN 'WINDOWS_LOGIN' WHEN syslogins.isntgroup = 1 THEN 'WINDOWS_GROUP' ELSE 'SQL_USER' END
我收到此错误(多次):
消息 102,第 15 级,状态 1,第 35 行
'THEN' 附近的语法不正确。
【问题讨论】:
-
抛出的错误是什么?
-
Msg 102,级别 15,状态 1,第 35 行 'THEN' 附近的语法不正确。消息 102,级别 15,状态 1,第 35 行 'THEN' 附近的语法不正确。这突出显示: /* 获取具有权限的组成员 */ SELECT Msg 102, Level 15, State 1, Line 35 “THEN”附近的语法不正确。消息 102,级别 15,状态 1,第 35 行 'THEN' 附近的语法不正确。消息 102,级别 15,状态 1,第 35 行 'THEN' 附近的语法不正确。
-
sp_MSForEachDB 仅适用于 2000 个字符及以下的字符串 - 这可能是问题吗?解决这个问题的一个好方法是实现一个替代过程,就像我做的codereview.stackexchange.com/questions/117386/…
标签: sql-server tsql audit