如何为数据库中新建用户B复制用户A的表和视图权限?
故事背景:
公司使用的是SQL Server数据库,经常会碰到一种情况,需要为新入职的员工赋予同组内其他同事的权限。
常用方法:
- 1,为同一组申请创建统一的Security Group(安全组),为创建的组分配相关表和视图的访问权限。不管员工入职还是离职,仅需将组内的成员进行相关的添加和删除即可。
- 2,由于某些原因,如数据权限最小原则,员工A仅有数据库中某几张表和视图的查询权限。当员工A出现职位变动时,需要为接替者员工B赋予员工A的数据库访问权限。如果逐一给员工B添加相关表和视图的查询权限,则过程漫长,还有可能造成权限遗漏。
当前篇章我们主要详解第2种情况,应该怎样快速把数据库中员工A表和视图的查询权限快速赋予员工B呢?
解决方案:
1,在数据库中创建用户B(如果用户B的登录已存在,则只需创建映射用户B到该登录的数据库):
1 USE [ABC]; -- 切换到目标数据库 2 GO 3 4 -- 假设B是数据库用户,不是登录名 5 CREATE USER [B] FOR LOGIN [B]; -- 如果B是Windows登录或其他类型登录,需要相应地更改 6 GO
2,将用户A表查询权限赋予用户B:
由于直接复制权限比较复杂,需要遍历所有表和视图,并且检查用户A被授予的SELECT权限。然后再把查到的用户A的表和视图权限赋予用户B。
以下是如何为用户B授予用户A的SELECT权限的示例代码:
1 USE [ABC]; -- 确保使用正确的数据库 2 GO 3 4 DECLARE @TableName NVARCHAR(256); 5 DECLARE @SQL NVARCHAR(MAX) = ''; 6 7 -- 获取用户A在dbo架构下所有表和视图的SELECT权限,并构建授权语句 8 DECLARE TableCursor CURSOR FOR 9 SELECT QUOTENAME(t.name) 10 FROM sys.tables AS t 11 JOIN sys.database_permissions AS dp ON t.object_id = dp.major_id 12 WHERE dp.permission_name = 'SELECT' AND dp.grantee_principal_id = USER_ID('A') AND dp.class = 1 13 14 OPEN TableCursor; 15 FETCH NEXT FROM TableCursor INTO @TableName; 16 17 WHILE @@FETCH_STATUS = 0 18 BEGIN 19 SET @SQL = @SQL + 'GRANT SELECT ON ' + @TableName + ' TO [B];' + CHAR(13); 20 FETCH NEXT FROM TableCursor INTO @TableName; 21 END 22 23 CLOSE TableCursor; 24 DEALLOCATE TableCursor; 25 26 -- 执行构建的授权语句 27 EXEC sp_executesql @SQL; 28 GO 29 30 -- 同上,为视图赋予权限 31 DECLARE ViewCursor CURSOR FOR 32 SELECT QUOTENAME(v.name) 33 FROM sys.views AS v 34 JOIN sys.database_permissions AS dp ON v.object_id = dp.major_id 35 WHERE dp.permission_name = 'SELECT' AND dp.grantee_principal_id = USER_ID('A') AND dp.class = 0 36 37 OPEN ViewCursor; 38 FETCH NEXT FROM ViewCursor INTO @TableName; 39 40 WHILE @@FETCH_STATUS = 0 41 BEGIN 42 SET @SQL = @SQL + 'GRANT SELECT ON ' + @TableName + ' TO [B];' + CHAR(13); 43 FETCH NEXT FROM ViewCursor INTO @TableName; 44 END 45 46 CLOSE ViewCursor; 47 DEALLOCATE ViewCursor; 48 49 EXEC sp_executesql @SQL; 50 GO
请注意,上述脚本使用了动态SQL来构建权限授予的语句,并对每个表和视图执行了授权。QUOTENAME
函数用于确保表名和视图名被正确地引用,防止SQL注入。
此外,USER_ID('A')
函数获取用户A的数据库主ID,dp.class = 1
表示表(OBJECT),dp.class = 0
表示视图(VIEW)。在实际应用中,你可能需要根据实际情况调整上述脚本,以确保正确地复制所需的权限。
在执行这些操作之前,请确保你具有足够的权限,并且了解这些操作的后果,因为它们可能会对数据库的安全性和访问控制产生重大影响。
今天分享就到这,想了解更多小技巧,记得关注我哦!