web-dev-qa-db-fra.com

SQL Server - Comment accorder un accès en lecture à TOUTES les bases de données à une connexion?

Je dois donner un nouvel accès en lecture à toutes les 300 bases de données sur un serveur. Comment puis-je accomplir cela sans cocher 300 cases dans la zone de mappage de l'utilisateur?

18
Greg

Une solution consisterait à définir "Résultats en texte" dans le menu de requête dans SSMS, puis à exécuter la procédure ci-dessous.

En réalité, il ne fait pas le changement mais génère un script que vous pouvez réviser et exécuter.

SET NOCOUNT ON;

DECLARE @user_name    SYSNAME
        , @login_name SYSNAME;

SELECT @user_name = 'user_name',
       @login_name = 'login_name'

SELECT '
    USE ' + QUOTENAME(NAME) + ';

    CREATE USER ' + QUOTENAME(@user_name)
       + ' FOR LOGIN ' + QUOTENAME(@login_name)
       + ' WITH DEFAULT_SCHEMA=[dbo];

    EXEC sys.sp_addrolemember
      ''db_datareader'',
      ''' + QUOTENAME(@user_name) + ''';

    EXEC sys.sp_addrolemember
      ''db_denydatawriter'',
      '''
       + QUOTENAME(@user_name) + '''; 

GO
'
FROM   sys.databases
WHERE  database_id > 4
       AND state_desc = 'ONLINE' 

Vous pouvez aussi regarder sys.sp_MSforeachdbcomme ici ou la version améliorée d'Aaron Bertrand ici

Si vous ne voyez pas tous les caractères lors de l’exécution, ouvrez les Options de requête pour le texte et vérifiez le paramètre "Nombre maximal de caractères affichés dans chaque colonne". Assurez-vous qu'il est défini sur une valeur suffisamment grande pour afficher tous les caractères.

19
Martin Smith

Curseur à travers les bases de données et GRANT d'accès à chacun avec un petit t-sql.

Je n'ai pas testé le code ci-dessous.

DECLARE db_cursor CURSOR FOR
SELECT name 
FROM master.dbo.sysdatabases 
WHERE name NOT IN ('master','model','msdb','tempdb') 


WHILE @@FETCH_STATUS = 0  
BEGIN  

GRANT SELECT ON DATABASE::@name to 'username'; 

FETCH NEXT FROM db_cursor INTO @name  
END 
5
buckbova
EXEC sp_MSForEachDB 
'Declare @name varchar(100)
 select @name = ''?''
 PRINT @name
 IF db_id(@name) > 4
 BEGIN
 USE ?
 CREATE USER [user] FOR LOGIN [user];
EXEC sp_addrolemember ''db_datareader'', ''user''
 END'
4
Steven Van Epps
Declare @Databases Cursor
Declare @DbName as nvarchar(64)
Declare @Sql nvarchar(max)
Declare @BaseAddUserSql nvarchar(max)
Declare @BaseAddRoleSql nvarchar(max)

Set @Databases = Cursor Fast_Forward For
    select [name]
    from master..sysdatabases
    where [name] not in('master','model','msdb','tempdb')

Open @Databases
Fetch Next From @Databases Into @DbName

Set @BaseAddUserSql = 'exec sp_adduser ''LOGINNAME'''
Set @BaseAddRoleSql = 'exec sp_addrolemember ''db_datareader'', ''LOGINNAME'''


While @@Fetch_Status = 0
Begin
    Begin Try
        Set @Sql = 'Use ' + Quotename(@DbName)
        exec (@Sql)

        Set @Sql = Replace(@BaseAddUserSql, 'LOGINNAME', <loginname>)
        exec(@Sql)

        Set @Sql = Replace(@BaseAddRoleSql, 'LOGINNAME', <loginname>)
        exec(@Sql)
    End Try
    Begin Catch
    End Catch

    Fetch Next From @Databases Into @DbName
End

Close @Databases
Deallocate @Databases
2
Thomas

Je devais modifier légèrement la réponse de Martin Smith comme suit:

  1. Les espaces et les sauts de ligne n'ont pas permis de générer tout le texte correctement
  2. Le QUOTENAME dans l'instruction Exec est mis entre crochets, ce qui est incorrect.

Ma version:

SET NOCOUNT ON;

DECLARE @user_name    SYSNAME
        , @login_name SYSNAME;

SELECT @user_name = 'HelpdeskUser',
       @login_name = 'Helpdesk'

SELECT 'USE ' + QUOTENAME(NAME) + ';
        CREATE USER ' + QUOTENAME(@user_name)
       + ' FOR LOGIN ' + QUOTENAME(@login_name)
       + ' WITH DEFAULT_SCHEMA=[dbo];
    EXEC sys.sp_addrolemember ''db_datareader'',''' + @user_name + ''';
    EXEC sys.sp_addrolemember ''db_denydatawriter'', ''' + @user_name + '''; 
GO'
FROM   sys.databases
WHERE  database_id > 4
       AND state_desc = 'ONLINE' 

Sinon, fonctionne parfaitement. Merci

2
Gorata - OkomelaIT

J'avais juste besoin d'un utilisateur qui aura accès à toutes les bases de données avec une autorisation de lecture de données. J'ai donc utilisé ce code: Vous devrez exécuter le résultat à partir de la requête.

USE [master]
GO CREATE LOGIN [DOMAIN\USER] FROM WINDOWS WITH DEFAULT_DATABASE=[master] GO
select 'use ['+name+']
CREATE USER [DOMAIN\USER] FOR LOGIN [DOMAIN\USER]
EXEC sp_addrolemember N''db_datareader'', N''DOMAIN\USER''
'
from sys.databases

si vous ne souhaitez pas l'appliquer aux bases de données système, ajoutez simplement où database_id> 6

0
DnL

Vous pouvez utiliser par exemple Cursor , comme ceci:

USE master
GO

DECLARE @DatabaseName VARCHAR(32)   
DECLARE @SQL NVARCHAR(max)
DECLARE @User VARCHAR(64)
SET @User = '[SQL\srvSSISAcc]' --Your User

DECLARE Grant_Permission CURSOR LOCAL FOR
SELECT name FROM MASTER.dbo.sysdatabases
WHERE name NOT IN ('master','model','msdb','tempdb')  

OPEN Grant_Permission  
FETCH NEXT FROM Grant_Permission INTO @DatabaseName  
WHILE @@FETCH_STATUS = 0  
BEGIN  

    SELECT @SQL = 'USE '+ '[' + @DatabaseName + ']' +'; '+ 'CREATE USER ' + @User + 
    'FOR LOGIN ' + @User + '; EXEC sp_addrolemember N''db_datareader'', 
    ' + @User + '; EXEC sp_addrolemember N''db_datawriter'', ' + @User + ''

    EXEC sp_executesql @SQL
    PRINT @SQL

FETCH NEXT FROM Grant_Permission INTO @DatabaseName  
END  
CLOSE Grant_Permission  
DEALLOCATE Grant_Permission 

Plus d’informations dans mon article à ce sujet: http://www.pigeonsql.com/single-post/2016/12/23/Grant-User-Access-to-All-Databases

0
Filip Holub