SQL Server - 如何将所有数据库的读取权限授予登录名?
Posted
技术标签:
【中文标题】SQL Server - 如何将所有数据库的读取权限授予登录名?【英文标题】:SQL Server - How to Grant Read Access to ALL databases to a Login? 【发布时间】:2011-03-06 10:53:42 【问题描述】:我需要授予对服务器上所有 300 个数据库的新登录读取访问权限。如果不选中用户映射区域中的 300 个复选框,我该如何完成此操作?
【问题讨论】:
由于这是一个非常古老的问题,仍然有很多观点,请注意,在 SQL 2014+ 中,GRANT CONNECT ANY DATABASE TO <SQL_Login>;
和 GRANT SELECT ALL USER SECURABLES TO <SQL_Login>;
将比旧的方法容易得多做事。
【参考方案1】:
一种方法是在 SSMS 的查询菜单上设置“结果为文本”,然后执行以下操作。
它实际上并没有进行更改,而是生成一个脚本供您查看和执行。
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'
或者你可以看看sys.sp_MSforeachdb
as here或Aaron Bertrand的改进版here
如果您在运行此程序时没有看到所有字符,请打开“文本查询选项”并检查“每列中显示的最大字符数”的设置。确保将其设置为足够大的值以显示所有字符。
【讨论】:
为什么我现在才听说这个 sp_msforeachdb?我想我只是试着用我知道的工具弄清楚一切。好吧,我正在将它添加到工具箱中。谢谢! 谢谢!这似乎奏效了。我确实将该查询的结果复制到文本板中,并将 Go 替换为 \nGo\n @Greg - 很高兴它成功了。您是否在 Management Studio 中运行过它?如果是这样,选择“结果到文本”选项(CTRL + T)可能会避免中间步骤的需要。 默认 SQL 文本列限制为 256,因此您需要在查询 -> 查询选项 -> 结果 -> 文本中增加此限制,以避免生成的脚本被截断。 用户名和登录名周围的QUOTENAME
对我不起作用(SQL2019)。【参考方案2】:
您可以使用例如 Cursor,像这样:
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
在我的帖子中找到有关此主题的更多信息: http://www.pigeonsql.com/single-post/2016/12/23/Grant-User-Access-to-All-Databases
【讨论】:
【参考方案3】:我只需要一个可以访问所有具有数据读取权限的数据库的用户,所以我使用了以下代码: 顺便说一句,您需要运行查询的结果。
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
如果您不想将其应用于系统数据库,只需添加 其中database_id > 6
【讨论】:
【参考方案4】:我不得不稍微调整一下 Martin Smith 的答案:
-
空格和换行符导致并非所有文本都正确生成
Exec 语句中的 QUOTENAME 放在方括号中,这是不正确的。
我的版本:
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'
否则完美运行。 谢谢
【讨论】:
【参考方案5】: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'
【讨论】:
【参考方案6】:使用一点 t-sql 浏览数据库并授予对每个数据库的访问权限。
我没有测试下面的代码。
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
【讨论】:
在那之后使用的 t-sql 是我的困惑点。对此有任何指示吗?【参考方案7】: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
【讨论】:
它说它已成功完成,但我没有看到任何变化。用户映射区域没有改变。我为以上是关于SQL Server - 如何将所有数据库的读取权限授予登录名?的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 Dapper 从 SQL Server Image 字段中读取 blob 数据?
如何读取、编辑和写入xls文件,然后导出到SQL Server
如何将SQL Server中多个表的数据一次性返回到一张EXCEL工作表(Sheet)中
SQL Server - 授予对所有现有和未来数据库的读取访问权限的登录权限
如何将所有数据库(快速)自 sql server 2008 express 传递到 sql server 2008 R2(无 express)