我在一台服务器上有 980 个数据库,我应该授予几个用户只读访问权限。
我当然不想运行alter DB add user...
语句,因为它绝对是耗时的。
不知道有没有用exec sp_addrolemember 'db_datareader', 'user'
?
有人可以让我知道是否可以做其他事情吗?
这是我在 Powershell 中的做法:
$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}
Run Code Online (Sandbox Code Playgroud)
这假设已经创建了登录名 foo。它还假定在 localhost 实例上运行。
sp_addrolemember
将用户添加到角色,它不会自动在数据库中创建用户。
您可以使用动态 SQL 来运行此程序,前提是您可以通过编程方式识别需要添加用户的数据库。
以下将打印代码以将单个用户添加到实例中的每个非系统数据库:
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;
Run Code Online (Sandbox Code Playgroud)
我在这里使用了一个游标来单独PRINT
为每个数据库创建语句。SomeUser
在运行此代码之前,您需要手动创建登录名。