2013-03-13 62 views
3

偶尔我必须从我们的生产SQL服务器来测试SQL实例恢复数据库的。数据库恢复后,我们手动为恢复的数据库恢复正确的访问权限(例如数据库所有者/读者/写者)。此过程相当不错,除非必须在还原之前手动截取权限,然后从拍摄的图像中重新应用它们。T-SQL脚本当前用户的数据库权限

有没有使用T-SQL存储当前权限的用户数据库之前恢复,然后重新应用这些相同的权限,一旦修复完成一个简单的方法?

回答

0

有一个非常有用的功能: sys.fn_my_permissions(可靠的,“securable_class”) 它使您能够看到当前用户的权限EFFECTICVE到指定的对象,所以我不知道,如果你可以简单地建立GRANT/DENY来自它的命令。我从来没有用过这种方式。 在你的情况下,你运行它作为另一个用户:

EXECUTE AS USER = '<username>'; 
GO 
SELECT * 
FROM fn_my_permissions(null, 'SERVER') 
GO 

SELECT * 
FROM fn_my_permissions('<DBNAME>', 'Database') 
ORDER BY subentity_name, permission_name ; 

REVERT; 
GO 
+0

谢谢您的回应:)是的,这是一个非常有用的功能。你知道是否有办法以t-sql格式返回权限,以便通过运行返回的脚本来重新应用它们? – user2165609 2013-03-14 06:33:42

0

你正在处理被称为orphaned users的问题。

下面是我在过去使用的脚本(我不得不从内存中把这个在一起,你应该仔细验证):

create table #users (UserName sysname, UserSID varbinary(85)) 

Insert into #users 
exec sp_change_users_login @Action='Report'; 

declare mycursor cursor for select * from #users; 
open mycursor; 

declare @UserName sysname; 
declare @UserSID varbinary(85); 

fetch next from mycursor 
into @UserName, @UserSID 

while @@FETCH_STATUS = 0 
begin 
    exec sp_change_users_login @Action='update_one', @[email protected], @[email protected]; 
end 
close mycursor; 
deallocate mycursor; 

这个脚本使得一个重要的假设。用户登录名和他们在数据库中的用户名匹配。如果不是这样,您将不得不更改发送给sp_change_users_login的@LoginName参数。

+0

谢谢你这么多的响应:)你的脚本是有效的,但它是没有这么多的问题孤立用户。我需要一种方式来在DB恢复之前编写用户权限的脚本。之后,我会使用该脚本重新应用所记录的权限。我有道理吗? :/ – user2165609 2013-03-14 06:32:17

1
SELECT 
dp.permission_name collate latin1_general_cs_as AS Permission, 
t.TABLE_SCHEMA + '.' + o.name AS Object, 
dpr.name AS Username 
FROM sys.database_permissions AS dp 
INNER JOIN sys.objects AS o ON dp.major_id=o.object_id 
INNER JOIN sys.schemas AS s ON o.schema_id = s.schema_id 
INNER JOIN sys.database_principals AS dpr ON dp.grantee_principal_id=dpr.principal_id 
INNER JOIN INFORMATION_SCHEMA.TABLES t 
     ON TABLE_NAME = o.name     
WHERE dpr.name NOT IN ('public','guest') 
ORDER BY 
    Permission, Object,Username 
3

您的问题的答案很可能是来自杰夫的答案。

但是从霍华德的剧本是非常实用的,我只是增加一列,它与信息,生成TSQL语法。您可以复制该文件并以SQL身份运行以将权限复制到另一个数据库。

SELECT 
dp.permission_name collate latin1_general_cs_as AS Permission, 
t.TABLE_SCHEMA + '.' + o.name AS Object, 
dpr.name AS Username 
, 'GRANT ' + dp.permission_name collate latin1_general_cs_as 
    + ' ON ' 
    + t.TABLE_SCHEMA 
    + '.' 
    + o.name 
    + ' TO ' 
    + dpr.name 
FROM sys.database_permissions AS dp 
INNER JOIN sys.objects AS o ON dp.major_id=o.object_id 
INNER JOIN sys.schemas AS s ON o.schema_id = s.schema_id 
INNER JOIN sys.database_principals AS dpr ON dp.grantee_principal_id=dpr.principal_id 
INNER JOIN INFORMATION_SCHEMA.TABLES t 
    ON TABLE_NAME = o.name     
WHERE dpr.name NOT IN ('public','guest') 
ORDER BY 
    Permission, Object,Username 
+0

他说权限,但他从什么去上说,他的意思rolemembers,此脚本不会做。 – Paul 2014-06-26 09:53:30

+0

这是好的,但不适用于存储的特效。我不得不手动编写脚本,即GRANT EXECUTE ON ... – 2016-03-01 06:14:59

0

与有关权限的回答结合这:

SELECT 'EXEC sp_addrolemember @rolename =' 
+ SPACE(1) + QUOTENAME(USER_NAME(rm.role_principal_id), '') 
+ ', @membername =' + SPACE(1) + QUOTENAME(USER_NAME(rm.member_principal_id), '') 
AS 'Role Memberships' 
FROM sys.database_role_members AS rm 
ORDER BY rm.role_principal_id 
0

这里是脚本@Fabian写了修改后的版本,这样我也可以编写脚本为存储过程的权限。还增加了QUOTENAME,所以适当的东西在括号内。

SELECT 
    dp.permission_name collate latin1_general_cs_as AS Permission, 
    t.TABLE_SCHEMA + '.' + o.name AS TableName, 
    rt.ROUTINE_SCHEMA + '.' + o.name AS ProcedureName, 
    dpr.name AS Username 
    , 'GRANT ' + dp.permission_name collate latin1_general_cs_as 
     + ' ON ' 
     + QUOTENAME(CASE WHEN t.TABLE_SCHEMA IS NOT NULL THEN t.TABLE_SCHEMA ELSE rt.ROUTINE_SCHEMA END) 
     + '.' 
     + QUOTENAME(o.name) 
     + ' TO ' 
     + QUOTENAME(dpr.name) 
FROM sys.database_permissions AS dp 
INNER JOIN sys.objects AS o ON dp.major_id=o.object_id 
INNER JOIN sys.schemas AS s ON o.schema_id = s.schema_id 
INNER JOIN sys.database_principals AS dpr ON dp.grantee_principal_id=dpr.principal_id 
LEFT outer JOIN INFORMATION_SCHEMA.TABLES t ON TABLE_NAME = o.name    
LEFT OUTER JOIN INFORMATION_SCHEMA.ROUTINES rt ON rt.ROUTINE_NAME = o.name 
WHERE dpr.name NOT IN ('public','guest') 
ORDER BY Permission, TableName, ProcedureName, Username