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


19

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

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

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


Answers:


15

这是使用动态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, p.default_schema_name, 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;

1
有趣的是,我必须为p.name和p.default_schema_name列添加显式排序规则,以使联合全部正常工作
Michael J Swart 2014年

@MichaelJSwart嗯,是的,在数据​​库具有不同的排序规则时,我曾经遇到过这种情况(某些元数据列使用服务器排序规则,而其他元数据列则使用数据库排序规则)。我希望唯一真正被烧死的人是那些坚持在实体名称中使用古怪字符的人,这些字符仅在某些晦涩的排序规则中得到支持...
艾伦·伯特兰

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' 

感谢Taiob,这个方法很好用,(我将database_name列括在方括号(“ [”和“]”)中)
Michael J Swart

5

尝试sp_dbpermissions。它可能会为您提供所需信息,但它会做您想做的事情。

安装完成后,运行此程序。

sp_dbpermissions @dbname = 'All', @LoginName = 'LoginName'

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


4

这是一个Powershell解决方案:

import-module sqlps;

$s = new-object microsoft.sqlserver.management.smo.server '.'
foreach ($db in $s.Databases | where {$_.IsAccessible -eq $true}) {
   $u = $db.users | where {$_.Login -eq 'foobar'}
   if ($u -ne $null) { #login is mapped to a user in the db
       foreach ($role in $db.Roles) {
           if ($role.EnumMembers() -contains $u.Name) {
               $u | select parent, @{name="role";expression={$role.name}}, name
           }
       }
   }
}

4

可悲的是,您将不得不遍历所有数据库才能获取信息。你会想加入sys.database_principalssys.server_principals有关SID每个数据库匹配。

不要使用,sp_msforeachdb因为它有时会丢失数据库。


1

我正在寻找类似的答案并找到了这个答案:https : //www.pythian.com/blog/httpconsultingblogs-emc-comjamiethomsonarchive20070209sql-server-2005_3a00_-view-all-permissions-_2800_2_2900_-aspx/。是的,它使用了可怕的sp_MSforeachDB,但是我认为那个人有时会受到不好的说唱... ;-)

我将在此处发布SQL以方便复制粘贴(我为此而功劳,只是使其易于访问!):

DECLARE @DB_Users TABLE (DBName sysname, UserName sysname, LoginType sysname
, AssociatedRole varchar(max), create_date datetime, modify_date datetime)

INSERT @DB_Users
EXEC sp_MSforeachdb
'use [?]
SELECT ''?'' AS DB_Name,
case prin.name when ''dbo'' then prin.name + '' (''
    + (select SUSER_SNAME(owner_sid) from master.sys.databases where name =''?'') + '')''
    else prin.name end AS UserName,
    prin.type_desc AS LoginType,
    isnull(USER_NAME(mem.role_principal_id),'''') AS AssociatedRole, 
    create_date, modify_date
FROM sys.database_principals prin
LEFT OUTER JOIN sys.database_role_members mem
    ON prin.principal_id=mem.member_principal_id
WHERE prin.sid IS NOT NULL and prin.sid NOT IN (0x00)
and prin.is_fixed_role <> 1 AND prin.name NOT LIKE ''##%'''

SELECT dbname, username, logintype, create_date, modify_date,
    STUFF((SELECT ',' + CONVERT(VARCHAR(500), associatedrole)
        FROM @DB_Users user2
        WHERE user1.DBName=user2.DBName AND user1.UserName=user2.UserName
        FOR XML PATH('')
    ),1,1,'') AS Permissions_user
FROM @DB_Users user1
WHERE user1.UserName = N'<put your login-name here!>'
GROUP BY dbname, username, logintype, create_date, modify_date
ORDER BY DBName, username

-1

下面的查询应返回所请求的DbName的映射

SELECT 'DbName', dbPri.name, dbPri1.name
FROM [DbName].sys.database_principals dbPri 
JOIN [DbName].sys.database_role_members dbRoleMem ON dbRoleMem.member_principal_id = 
dbPri.principal_id
JOIN [DbName].sys.database_principals dbPri1  ON dbPri1.principal_id = 
dbRoleMem.role_principal_id
WHERE dbPri.name != 'dbo'

改进的查询如下

declare @sql varchar(Max)

 set @sql = 'use ? SELECT ''?'', dbPri.name, dbPri1.name
 FROM sys.database_principals dbPri 
 JOIN sys.database_role_members dbRoleMem ON 
 dbRoleMem.member_principal_id = 
 dbPri.principal_id
 JOIN sys.database_principals dbPri1  ON dbPri1.principal_id = 
 dbRoleMem.role_principal_id
 WHERE dbPri.name != ''dbo'''

 EXEC sp_MSforeachdb @sql

谢谢,此脚本的目标是为所有数据库找到一个映射。您的脚本仅提供一个特定数据库的信息,而不是全部数据库。
Michael J Swart '18

谢谢您的反馈,我认为可以重复。现在已更新,其中包含改进的查询
dilipkumar katre

请参阅@ Aaron-Bertrand的答案,并评论他对sp_MSforeachdb的想法。
Michael J Swart '18

-3

EXEC master..sp_msloginmappings


sp_msloginmappings在发布之前,您是否检查了无证件和不受支持的内容?
Kin Shah
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.