주어진 로그인에 대한 모든 매핑 된 사용자를 나열하는 쿼리


19

특정 로그인의 속성을 볼 때 해당 로그인에 매핑 된 사용자 목록을 볼 수 있습니다. 여기에 이미지 설명을 입력하십시오

SSMS (SQL Server Management Studio)를 프로파일 링했으며 SSMS가 한 번에 하나씩 모든 데이터베이스에 연결하고 sys.database_permissions에서 정보를 검색하는 것을 확인했습니다.

위에 표시된 사용자 매핑 정보를 검색하는 단일 쿼리를 작성할 수 있습니까? 아니면 커서 나 sp_MSforeachdb 등을 사용해야합니까?


답변:


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

@MichaelJSwart Ah 예, 데이터베이스에 다른 데이터 정렬이있을 때 (이것은 일부 메타 데이터 열이 서버 데이터 정렬을 사용하지만 다른 데이터 정렬은 상속합니다) 나는 실제로 불타고있는 유일한 사람들이 모호한 데이터 정렬에서만 지원되는 엔티티 이름에 엉뚱한 캐릭터를 사용한다고 주장하는 사람들이 있기를 바랍니다.
Aaron Bertrand

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 열을 괄호 ( '['and ']')로 묶습니다)
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을 게시합니다 NOT ,이에 대한 크레딧을 복용 그냥 쉽게 접근 할 수 있도록!)

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

의견을 보내 주셔서 감사합니다. 반복 될 수 있다고 생각했습니다. 이제 향상된 쿼리를 업데이트
dilipkumar katre

sp_MSforeachdb에 대한 @ Aaron-Bertrand의 답변과 의견을 참조하십시오.
Michael J Swart

-3

무엇에 대해 EXEC master..sp_msloginmappings?


sp_msloginmappings게시하기 전에 확인 이 문서화되지 않았으며 지원되지 않습니까?
Kin Shah
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.