故事背景:
公司使用的是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)。在实际应用中,你可能需要根据实际情况调整上述脚本,以确保正确地复制所需的权限。
在执行这些操作之前,请确保你具有足够的权限,并且了解这些操作的后果,因为它们可能会对数据库的安全性和访问控制产生重大影响。
今天分享就到这道,想了解更多小技巧,记得关注我哦!