列出给定登录的所有映射用户的查询

Mic*_*art 22 sql-server-2008 security sql-server permissions logins

查看特定登录的属性时,可以看到映射到该登录的用户列表: 在此处输入图片说明

我分析了 SQL Server Management Studio (SSMS),我看到 SSMS 一次连接到每个数据库并从 sys.database_permissions 检索信息

是否可以编写一个查询来检索上面显示的用户映射信息,或者我是否被迫使用游标或 sp_MSforeachdb 或类似的东西?

Aar*_*and 17

这是使用动态 SQL 的一种方法。没有迭代就没有任何方法可以做到这一点,但是这种方法比没有记录的、不受支持的和有缺陷的选项sp_MSforeachdb(例如(背景在这里这里))安全得多。

这将获得所有在线数据库的列表、映射的用户(如果存在)、默认模式名称以及它们所属角色的逗号分隔列表。

DECLARE @name sysname = N'your login name'; -- input param, presumably

DECLARE @sql nvarchar(max) = N'';

SELECT @sql += N'UNION ALL SELECT N''' + REPLACE(name,'''','''''') + ''',
    p.name                 COLLATE SQL_Latin1_General_CP1_CI_AS, 
    p.default_schema_name  COLLATE SQL_Latin1_General_CP1_CI_AS, 
    STUFF((SELECT N'','' + r.name 
      FROM ' + QUOTENAME(name) + N'.sys.database_principals AS r
      INNER JOIN ' + QUOTENAME(name) + N'.sys.database_role_members AS rm
      ON r.principal_id = rm.role_principal_id
      WHERE rm.member_principal_id = p.principal_id
      FOR XML PATH, TYPE).value(N''.[1]'',''nvarchar(max)''),1,1,N'''')
    FROM sys.server_principals AS sp
    LEFT OUTER JOIN ' + QUOTENAME(name) + '.sys.database_principals AS p
    ON sp.sid = p.sid
    WHERE sp.name = @name '
  FROM sys.databases WHERE [state] = 0;

SET @sql = STUFF(@sql, 1, 9, N'');

PRINT @sql;
EXEC master.sys.sp_executesql @sql, N'@name sysname', @name;
Run Code Online (Sandbox Code Playgroud)

在更现代的版本(2017+)上,我仍然会使用动态 SQL,但我会使用STRING_AGG()而不是FOR XML PATH,可能是这样的:

DECLARE @login sysname = N'your login name';

DECLARE @sql  nvarchar(max), 
        @sid  varbinary(85),
        @coll nvarchar(64) = N'COLLATE SQL_Latin1_General_CP1_CI_AS';

SELECT @sid = [sid] FROM sys.server_principals AS dp WHERE name = @login;

;WITH d AS 
(
  SELECT dbid = CONVERT(varchar(11), database_id),
         qn = QUOTENAME(name)
    FROM sys.databases WHERE [state] = 0
)
SELECT @sql = STRING_AGG(CONVERT(nvarchar(max),
        N'SELECT db = d.name, username = dp.name ' + @coll + ', 
        schemaname = dp.default_schema_name ' + @coll + ',
        roles = STRING_AGG(rp.name ' + @coll + ', N'','')
        FROM sys.databases AS d
        LEFT OUTER JOIN ' + qn + '.sys.database_principals AS dp ON dp.sid = @sid
        LEFT OUTER JOIN ' + qn + '.sys.database_role_members AS rm
        ON dp.principal_id = rm.member_principal_id
        LEFT OUTER JOIN ' + qn + '.sys.database_principals AS rp
        ON rp.principal_id = rm.role_principal_id
        WHERE d.database_id = ' + dbid + N'
        GROUP BY d.name, dp.name, dp.default_schema_name'
    ), char(13) + char(10) + N' UNION ALL ')
FROM d;

PRINT @sql;
EXEC master.sys.sp_executesql @sql, N'@sid varbinary(85)', @sid;
Run Code Online (Sandbox Code Playgroud)

在后一个示例中,如果您只想将用户映射到命名登录的数据库,只需将第一个左联接更改为内部联接。

  • 有趣的注意事项,我必须向 p.name 和 p.default_schema_name 列添加显式排序规则,以便联合全部正常工作 (2认同)

Sql*_*ide 7

这个脚本是从一个提到的脚本稍微修改过的,可以做你正在寻找的。用您需要信息的登录名替换“ThursdayClass”。 https://www.simple-talk.com/sql/sql-tools/the-sqlcmd-workbench/

    SET NOCOUNT ON
    CREATE TABLE #temp
        (
          SERVER_name SYSNAME NULL ,
          Database_name SYSNAME NULL ,
          UserName SYSNAME ,
          GroupName SYSNAME ,
          LoginName SYSNAME NULL ,
          DefDBName SYSNAME NULL ,
          DefSchemaName SYSNAME NULL ,
          UserID INT ,
          [SID] VARBINARY(85)
        )

    DECLARE @command VARCHAR(MAX)
    --this will contain all the databases (and their sizes!)
    --on a server
    DECLARE @databases TABLE
        (
          Database_name VARCHAR(128) ,
          Database_size INT ,
          remarks VARCHAR(255)
        )
    INSERT  INTO @databases--stock the table with the list of databases
            EXEC sp_databases

    SELECT  @command = COALESCE(@command, '') + '
    USE ' + database_name + '
    insert into #temp (UserName,GroupName, LoginName,
                        DefDBName, DefSchemaName,UserID,[SID])
         Execute sp_helpuser
    UPDATE #TEMP SET database_name=DB_NAME(),
                     server_name=@@ServerName
    where database_name is null
    '
    FROM    @databases
    EXECUTE ( @command )

    SELECT  loginname ,
            UserName ,
            Database_name
    FROM    #temp
    WHERE   LoginName = 'ThursdayClass' 
Run Code Online (Sandbox Code Playgroud)


Ken*_*her 5

试试sp_dbpermissions。它可能会给你比你需要的更多的信息,但它会做你想做的。

安装后运行这个。

sp_dbpermissions @dbname = 'All', @LoginName = 'LoginName'
Run Code Online (Sandbox Code Playgroud)

目前公平警告它执行“喜欢”匹配,因此如果其他登录名相似且匹配,那么您也会看到它们。例如,MyLoginMyLoginForThis都将匹配MyLogin。如果这是一个问题,我有一个尚未发布的版本,您可以将其关闭。让我知道,我可以通过电子邮件将其发送给您。