2013-03-13 57 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