2010-03-15 10 views
6

Myślę, że procedura powinna być mniej więcej tak:Jak uzyskać listę wszystkich użytkowników baz danych instancji

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 

Ale problemem jest to, że exec („używać” + @db) nie działa. I zawsze otrzymuję listę użytkowników z aktualnie wybranej bazy danych. Jak mam to naprawić?

P.S .: Chcę, aby ten kod działał na serwerach SQL 2000 i 2005.

Odpowiedz

10

Można również użyć nieudokumentowane, ale dobrze wykorzystane sp_MSforeachdb przechowywanej proc - patrz here for details lub zobaczyć inny blog post here:

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

znaku "?" jest symbolem zastępczym nazwy bazy danych, która zostanie dodana do polecenia, ponieważ zostanie wykonana względem każdej bazy danych w systemie.

+0

+1 Fantastyczny! Próbowałem wymyślić sposób, aby kod stee1rat działał w jakiś sposób, ucząc się w międzyczasie, a następnie wymyśliłeś tę wspaniałą przechowywaną procedurę sp_MSforeachdb! Dzięki! –

+1

Po prostu świetnie! Dziękuję Ci bardzo! Teraz mogę wygodnie upuścić użytkownika we wszystkich bazach danych za pomocą prostego polecenia exec sp_msforeachdb "use?; exec sp_dropuser '' testuser123 '' ':) Zastanawiam się, dlaczego ta procedura nie jest udokumentowana? To jest tak pomocne :) – stee1rat

2

Oto ładne zapytanie z http://www.sqlservercentral.com/scripts/Administration/63841/ Jeśli nie masz konta, jest to darmowa rejestracja i bardzo fajny zasób.

Umieszcza wszystko w tabeli tymczasowej, dzięki czemu możesz robić, co chcesz.

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

To nadal działa w SQL Server 2012 po zastąpieniu wiersza 'ELSE IF LEFT (CAST (Serverproperty (" ProductVersion ") AS VARCHAR (1)), 1) = '9'' z' ELSE IF LEFT (CAST (ServerProperty ("ProductVersion") AS VARCHAR (2)), 2) = '11''. (Oczywiście kontrola może być bardziej ogólna). – knb

Powiązane problemy