AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / dba / Perguntas / 81595
Accepted
Michael J Swart
Michael J Swart
Asked: 2014-11-01 07:06:51 +0800 CST2014-11-01 07:06:51 +0800 CST 2014-11-01 07:06:51 +0800 CST

Uma consulta que lista todos os usuários mapeados para um determinado login

  • 772

Ao observar as propriedades de um determinado login, é possível ver uma lista de usuários mapeados para esse login: insira a descrição da imagem aqui

Criei o perfil do SQL Server Management Studio (SSMS) e vejo que o SSMS se conecta a todos os bancos de dados um de cada vez e recupera informações de sys.database_permissions

É possível escrever uma única consulta que recupere as informações de mapeamento do usuário mostradas acima ou sou forçado a usar um cursor ou sp_MSforeachdb ou algo parecido?

sql-server sql-server-2008
  • 8 8 respostas
  • 90570 Views

8 respostas

  • Voted
  1. Best Answer
    Aaron Bertrand
    2014-11-01T08:18:24+08:002014-11-01T08:18:24+08:00

    Aqui está uma maneira usando SQL dinâmico. Não há realmente nenhuma maneira de fazer isso sem iterar, mas essa abordagem é muito mais segura do que opções não documentadas, sem suporte e com erros, como sp_MSforeachdb(background here and here ).

    Isso obterá uma lista de todos os bancos de dados online, o usuário mapeado (se existir), juntamente com o nome do esquema padrão e uma lista separada por vírgulas das funções às quais eles pertencem.

    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;
    

    Em versões mais modernas (2017+), eu ainda usaria SQL dinâmico, mas usaria STRING_AGG()em vez de FOR XML PATH, provavelmente algo assim:

    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;
    

    Neste último exemplo, se você quiser apenas os bancos de dados com um usuário mapeado para o logon nomeado, basta alterar a primeira junção esquerda para uma junção interna.

    • 20
  2. SqlWorldWide
    2014-11-01T08:07:59+08:002014-11-01T08:07:59+08:00

    Este script é ligeiramente modificado a partir de um script mencionado em fará o que você está procurando. Substitua 'ThursdayClass' pelo login para o qual você precisa de informações. 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' 
    
    • 7
  3. Kenneth Fisher
    2014-11-01T07:34:20+08:002014-11-01T07:34:20+08:00

    Tente sp_dbpermissions . Provavelmente fornecerá mais informações do que você precisa, mas fará o que você deseja.

    Uma vez instalado, execute isso.

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

    Aviso justo no momento em que ele faz uma correspondência "like", portanto, se outros logins forem semelhantes e corresponderem, você os verá também. Por exemplo , MyLogine MyLoginForThisambos corresponderão em MyLogin. Se isso for um problema, tenho uma versão que ainda não lancei onde você pode desativá-la. Me avise e eu posso enviar por e-mail para você.

    • 6
  4. Nic
    2014-11-01T07:23:06+08:002014-11-01T07:23:06+08:00

    Infelizmente, você terá que percorrer todos os bancos de dados para obter as informações. Você desejará ingressar sys.database_principalsem sys.server_principalscada banco de dados correspondente no SID.

    Não use sp_msforeachdb, pois é conhecido por perder bancos de dados às vezes.

    • 4
  5. Ben Thul
    2014-11-01T09:38:11+08:002014-11-01T09:38:11+08:00

    Aqui está uma solução 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
  6. NateJ
    2016-02-25T12:16:15+08:002016-02-25T12:16:15+08:00

    Eu estava procurando uma resposta semelhante e encontrei isso: https://www.pythian.com/blog/httpconsultingblogs-emc-comjamiethomsonarchive20070209sql-server-2005_3a00_-view-all-permissions-_2800_2_2900_-aspx/ . E sim, ele usa o temido sp_MSforeachDB, mas acho que esse cara tem uma má reputação às vezes... ;-)

    Vou postar o SQL aqui para facilitar o copy-pasta (não estou recebendo crédito por isso, apenas tornando-o facilmente acessível!):

    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
  7. dilipkumar katre
    2018-12-17T23:49:18+08:002018-12-17T23:49:18+08:00

    A consulta abaixo deve retornar os mapeamentos para o DbName solicitado

    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'
    

    A consulta aprimorada está abaixo

    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
    
    • -1
  8. Nacho
    2016-07-06T05:09:45+08:002016-07-06T05:09:45+08:00

    E sobre EXEC master..sp_msloginmappings?

    • -3

relate perguntas

  • Quais são as principais causas de deadlocks e podem ser evitadas?

  • Quanto "Padding" coloco em meus índices?

  • Existe um processo do tipo "práticas recomendadas" para os desenvolvedores seguirem para alterações no banco de dados?

  • Como determinar se um Índice é necessário ou necessário

  • Downgrade do SQL Server 2008 para 2005

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    conectar ao servidor PostgreSQL: FATAL: nenhuma entrada pg_hba.conf para o host

    • 12 respostas
  • Marko Smith

    Como fazer a saída do sqlplus aparecer em uma linha?

    • 3 respostas
  • Marko Smith

    Selecione qual tem data máxima ou data mais recente

    • 3 respostas
  • Marko Smith

    Como faço para listar todos os esquemas no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Listar todas as colunas de uma tabela especificada

    • 5 respostas
  • Marko Smith

    Como usar o sqlplus para se conectar a um banco de dados Oracle localizado em outro host sem modificar meu próprio tnsnames.ora

    • 4 respostas
  • Marko Smith

    Como você mysqldump tabela (s) específica (s)?

    • 4 respostas
  • Marko Smith

    Listar os privilégios do banco de dados usando o psql

    • 10 respostas
  • Marko Smith

    Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Como faço para listar todos os bancos de dados e tabelas usando o psql?

    • 7 respostas
  • Martin Hope
    Jin conectar ao servidor PostgreSQL: FATAL: nenhuma entrada pg_hba.conf para o host 2014-12-02 02:54:58 +0800 CST
  • Martin Hope
    Stéphane Como faço para listar todos os esquemas no PostgreSQL? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh Por que o log de transações continua crescendo ou fica sem espaço? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland Listar todas as colunas de uma tabela especificada 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney O MySQL pode realizar consultas razoavelmente em bilhões de linhas? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx Como posso monitorar o andamento de uma importação de um arquivo .sql grande? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison Como você mysqldump tabela (s) específica (s)? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Jonas Como posso cronometrar consultas SQL usando psql? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas Como faço para listar todos os bancos de dados e tabelas usando o psql? 2011-02-18 00:45:49 +0800 CST

Hot tag

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve