2010-03-15 18 views
6

supongo que el procedimiento debería ser algo como esto:¿Cómo obtener una lista de usuarios de bases de datos de todas las instancias

declare @db varchar(100) 
declare @user varchar(100) 
declare c cursor for select name from sys.sysdatabases   

open c 

fetch next from c into @db 

while @@fetch_status = 0 
begin 
    print @db 
    exec ('use ' + @db) 

    declare u cursor for select name from sys.sysusers 
     where issqlrole <> 1 and hasdbaccess <> 0 and isntname <> 1 

    open u 

    fetch next from u into @user 

    while @@fetch_status = 0 
    begin 
     print @user 
     fetch next from u into @user 
    end 

    print '--------------------------------------------------' 
    close u  
    deallocate u  
    fetch next from c into @db 
end 

close c 
deallocate c 

Pero el problema es que exec ('utilizar' + @DB) no funciona. Y siempre obtengo una lista de usuarios de la base de datos elegida actualmente. ¿Cómo debería arreglar eso?

P.S .: Quiero que este código funcione en servidores 2000 y 2005 sql.

Respuesta

10

También puede utilizar el procedimiento almacenado sp_MSforeachdb indocumentado, pero bien utilizado - ver here for details o ver otro blog post here:

exec sp_MSforeachdb 'select * from ?.sys.sysusers' 

El "?" es el marcador de posición para el nombre de la base de datos que se agregará al comando, ya que se ejecuta contra cada base de datos en su sistema.

+0

+1 Awesome! ¡Estaba tratando de encontrar la forma de hacer que el código stee1rat funcione de una manera u otra, aprendiendo mientras tanto, y luego se llega a este magnífico procedimiento sp_MSforeachdb almacenado! ¡Gracias! –

+1

¡Es simplemente genial! ¡Muchas gracias! Ahora puedo soltar fácilmente al usuario en todas las bases de datos usando un simple comando exec sp_msforeachdb 'use?; exec sp_dropuser '' testuser123 '' ':) Me pregunto por qué este procedimiento no está documentado. Es muy útil :) – stee1rat

2

Aquí hay una buena consulta de http://www.sqlservercentral.com/scripts/Administration/63841/ Si no tiene una cuenta, es un registro gratuito y un recurso muy bueno.

Pone todo en una tabla temporal, luego puede hacer lo que quiera con ella.

USE MASTER 
GO 

BEGIN 
    IF LEFT(CAST(Serverproperty('ProductVersion') AS VARCHAR(1)), 1) = '9' 
     IF EXISTS (SELECT TOP 1 * 
        FROM Tempdb.sys.objects (nolock) 
        WHERE name LIKE '#TUser%') 
      DROP TABLE #TUser 
    ELSE 
     IF LEFT(CAST(Serverproperty('ProductVersion') AS VARCHAR(1)), 1) = '8' 
      IF EXISTS (SELECT TOP 1 * 
         FROM Tempdb.dbo.sysobjects (nolock) 
         WHERE name LIKE '#TUser%') 
       DROP TABLE #TUser 

     CREATE TABLE #tuser 
     (
      ServerName varchar(256), 
      DBName SYSNAME, 
      [Name] SYSNAME, 
      GroupName SYSNAME NULL, 
      LoginName SYSNAME NULL, 
      default_database_name SYSNAME NULL, 
      default_schema_name VARCHAR(256) NULL, 
      Principal_id INT, 
      sid VARBINARY(85) 
     ) 

     IF LEFT(CAST(Serverproperty('ProductVersion') AS VARCHAR(1)), 1) = '8' 
      INSERT INTO #TUser 
      EXEC sp_MSForEachdb 
      ' 
      SELECT 
      @@SERVERNAME, 
      ''?'' as DBName, 
      u.name As UserName, 
      CASE 
      WHEN (r.uid IS NULL) THEN ''public'' 
      ELSE r.name 
      END AS GroupName, 
      l.name AS LoginName, 
      NULL AS Default_db_Name, 
      NULL as default_Schema_name, 
      u.uid, 
      u.sid 
      FROM [?].dbo.sysUsers u 
      LEFT JOIN ([?].dbo.sysMembers m 
      JOIN [?].dbo.sysUsers r 
      ON m.groupuid = r.uid) 
      ON m.memberuid = u.uid 
      LEFT JOIN dbo.sysLogins l 
      ON u.sid = l.sid 
      WHERE u.islogin = 1 OR u.isntname = 1 OR u.isntgroup = 1 
      /*and u.name like ''tester''*/ 
      ORDER BY u.name 
      ' 
     ELSE IF LEFT(CAST(Serverproperty('ProductVersion') AS VARCHAR(1)), 1) = '9' 
      INSERT INTO #TUser 
      EXEC sp_MSForEachdb 
      ' 
      SELECT 
      @@SERVERNAME, 
      ''?'', 
      u.name, 
      CASE 
      WHEN (r.principal_id IS NULL) THEN ''public'' 
      ELSE r.name 
      END GroupName, 
      l.name LoginName, 
      l.default_database_name, 
      u.default_schema_name, 
      u.principal_id, 
      u.sid 
      FROM [?].sys.database_principals u 
      LEFT JOIN ([?].sys.database_role_members m 
      JOIN [?].sys.database_principals r 
      ON m.role_principal_id = r.principal_id) 
      ON m.member_principal_id = u.principal_id 
      LEFT JOIN [?].sys.server_principals l 
      ON u.sid = l.sid 
      WHERE u.TYPE <> ''R'' 
      /*and u.name like ''tester''*/ 
      order by u.name 
      ' 

    SELECT * 
    FROM #TUser 
    ORDER BY DBName, [name], GroupName 

    DROP TABLE #TUser 
END 
+0

Esto todavía funciona en SQL Server 2012 después de reemplazar la línea 'ELSE IF LEFT (CAST (Serverproperty ('ProductVersion') AS VARCHAR (1)), 1) = '9'' con' ELSE IF LEFT (CAST (propiedad del servidor ('ProductVersion') AS VARCHAR (2)), 2) = '11''. (Por supuesto, el cheque puede hacerse más general). – knb

Cuestiones relacionadas