2010-03-15 8 views
6

je suppose que la procédure devrait être quelque chose comme ceci:Comment obtenir une liste d'utilisateurs pour les bases de données de toutes les instances

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 

Mais le problème est que exec (« utiliser » + @db) ne fonctionne pas. Et je reçois toujours la liste des utilisateurs de la base de données actuellement choisie. Comment devrais-je résoudre ce problème?

P.S .: Je veux que ce code fonctionne sur les serveurs sql 2000 et 2005.

Répondre

10

Vous pouvez également utiliser les sans-papiers, mais bien utilisé sp_MSforeachdb stocké proc - voir here for details ou voir un autre blog post here:

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

Le "?" est l'espace réservé pour le nom de la base de données qui sera ajouté à la commande, car il est exécuté sur chaque base de données de votre système.

+0

+1 Génial! J'essayais de trouver un moyen de faire fonctionner le code de stee1rat d'une façon ou d'une autre, en apprenant le temps, et ensuite vous arrivez avec cette procédure stockée sp_MSforeachdb magnifique! Merci! –

+1

C'est génial! Merci beaucoup! Maintenant, je peux facilement déposer l'utilisateur dans toutes les bases de données en utilisant une simple commande exec sp_msforeachdb 'use? exec sp_dropuser '' testuser123 '' ':) Je me demande simplement pourquoi cette procédure n'est pas documentée? C'est tellement utile :) – stee1rat

2

Voici une belle requête de http://www.sqlservercentral.com/scripts/Administration/63841/ Si vous n'avez pas de compte, c'est une inscription gratuite et une très belle ressource.

Met tout dans une table temporaire, alors vous pouvez faire ce que vous voulez avec.

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

Cela fonctionne toujours dans SQL Server 2012 après avoir remplacé la ligne 'ELSE SI GAUCHE (CAST (Serverproperty ('ProductVersion') AS VARCHAR (1)), 1) = '9'' avec' ELSE SI GAUCHE (CAST (Serverproperty ('ProductVersion') AS VARCHAR (2)), 2) = '11''. (Bien sûr, le contrôle peut être fait plus général). – knb

Questions connexes