Fügen Sie Benutzer zu mehreren Datenbanken hinzu

7

Ich habe 980 DBs auf einem Server und soll einigen Benutzern schreibgeschützten Zugriff gewähren.

Ich möchte auf keinen Fall eine alter DB add user...Anweisung ausführen , da dies definitiv zeitaufwändig ist.

Ich weiß nicht, ob es exec sp_addrolemember 'db_datareader', 'user'funktioniert?

Kann mich jemand wissen lassen, ob noch etwas getan werden kann?

Syed
quelle
Bloggte über etwas Ähnliches hier, wenn Sie PowerShell verwenden möchten: pythian.com/blog/?p=77813

Antworten:

9

So würde ich es in Powershell machen:

$instance = 'localhost'
$dbs = dir SQLSERVER:\SQL\$instance\DEFAULT\Databases
$sql = 'CREATE USER [foo] FROM LOGIN [foo]; ALTER ROLE db_datareader ADD MEMBER [foo];'
$dbs | ForEach-Object {Invoke-Sqlcmd -ServerInstance $instance -Database $_.Name -Query $sql}

Dies setzt voraus, dass das Login foo bereits erstellt wurde. Es wird auch davon ausgegangen, dass es auf der localhost-Instanz ausgeführt wird.

Mike Fal
quelle
5

sp_addrolemember Fügt der Benutzer der Rolle hinzu, wird der Benutzer nicht automatisch in der Datenbank erstellt.

Sie können dynamisches SQL verwenden, um dies auszuführen, vorausgesetzt, Sie können programmgesteuert die Datenbanken identifizieren, in denen der Benutzer hinzugefügt werden muss.

Im Folgenden wird Code gedruckt, um jeder Nicht-Systemdatenbank in der Instanz einen einzelnen Benutzer hinzuzufügen:

DECLARE @UserName SYSNAME;
DECLARE @cmd NVARCHAR(MAX);
SET @cmd = '';

SET @UserName = 'SomeUser';

DECLARE cur CURSOR LOCAL FORWARD_ONLY
FOR 
SELECT 'USE ' + d.name + ';
GO
IF NOT EXISTS 
(
     SELECT 1 
     FROM sys.database_principals dp 
     WHERE dp.name = ''' + @UserName + '''
)
BEGIN
    CREATE USER ' + QUOTENAME(@UserName) + ' 
    FROM LOGIN ' + QUOTENAME(@UserName) + '
        WITH DEFAULT_SCHEMA = dbo;
END
EXEC sp_addrolemember @RoleName = ''db_datareader''
    , @MemberName = ''' + @UserName + ''';
GO

'
FROM sys.databases d
WHERE d.database_id > 4 /* exclude system databases.  Other criteria could
    be used here */

OPEN cur;
FETCH NEXT FROM cur 
INTO @cmd;

WHILE @@FETCH_STATUS = 0
BEGIN

    PRINT (@cmd);

    FETCH NEXT FROM cur 
    INTO @cmd;
END

CLOSE cur;
DEALLOCATE cur;

Ich habe hier einen Cursor verwendet, um PRINTdie Anweisung für jede Datenbank einzeln zu erstellen. Sie müssen die Anmeldung für manuell erstellen, SomeUserbevor Sie diesen Code ausführen können.

Max Vernon
quelle
2

Ich weiß, dass es viele bessere Antworten gibt, aber ich mag einfache Dinge.

 SELECT 
      'USE [' + name + N']' + CHAR(13) + CHAR(10)
      + 'create user [USER] for login [LOGIN]' + CHAR(13) + CHAR(10)
      + 'EXEC sp_addrolemember ''db_owner'', ''USER'''

FROM sys.databases

WHERE database_id > 4;
Racer SQL
quelle
1
Beachten Sie, dass - sp_addrolemember -> Diese Funktion in einer zukünftigen Version von Microsoft SQL Server entfernt wird. Vermeiden Sie die Verwendung dieser Funktion in neuen Entwicklungsarbeiten und planen Sie, Anwendungen zu ändern, die diese Funktion derzeit verwenden. Verwenden Sie stattdessen ALTER ROLE.
Kin Shah
Verwenden Sie auch besser Quotename als manuelles Setzen [und ]Klammern.
Kin Shah
1

Ein Nicht-Cursor-Ansatz wäre wie folgt. Ich gehe davon aus, dass die Anmeldung bereits vorhanden ist und das Schema standardmäßig verwendet wird dbo.

set nocount on
declare @user_to_be_added sysname
declare @sqltext nvarchar(max) = N''

-- change below to your user to be added .. make sure that the login is already existing
set @user_to_be_added = 'foobar'


select  @sqltext += char(10)+ 'use '+quotename(name)+';'+char(10)+ 'CREATE USER '+quotename(@user_to_be_added)+' FOR LOGIN '+quotename(@user_to_be_added)+';'+char(10)+
'ALTER USER '+quotename(@user_to_be_added)+' WITH DEFAULT_SCHEMA=[dbo];'+char(10)+ 'ALTER ROLE [db_datareader] ADD MEMBER '+quotename(@user_to_be_added)+'; '+ char(10) + 'go'
from sys.databases
where database_id > 4 -- exclude system databases

SELECT @sqltext
--- once you are happy with the output uncomment below line
-- EXEC sp_executesql @sqltext;
Kin Shah
quelle
Korrigieren Sie mich, wenn ich falsch liege, aber laufen Sie nicht Gefahr, nicht die gesamte Ausgabe zu sehen, wenn Sie eine so große Textmenge verketten und dann mit ausgeben PRINT? Mit viel Text meine ich, wenn ich dies in über 900 Datenbanken mache.
Max Vernon
1
@MaxVernon yeh das ist PRINTEinschränkung, besser ein SELECT zu verwenden und es auch in der Ausgabedatei zu speichern.
Kin Shah
-1

Mit einer undokumentierten Prozedur können Sie die SP_msforeachdbProzedur verwenden.

Zum Beispiel wäre die Ausführung etwas in der Art von

exec sp_msforeachdb '
use ?
if (dbid(''?'') > 4 )
BEGIN
    create user [user] from login [login];

    alter role db_datareader add member [user];'
END

Dies ist nicht die eleganteste Lösung, aber wenn Sie einfach versuchen möchten, jeder Benutzerdatenbank ein Login hinzuzufügen, würde dies funktionieren.

Ein kurzer Hinweis, wenn die SQL Server 2008 R2 oder älter verwenden würden Sie ersetzen mögen , die alter rolemit exec sp_addrolememberals von SQL Server 2012 und höher als die alte role Syntax nur hinzugefügt.

Ian Chamberland
quelle