Reputation: 69
Occasionally I have to restore DB's from our production SQL server to the test SQL instance. When the database has been restored, we manually restore the correct access permissions (e.g. DB owner/ reader/ writer) for the restored database. This process works fairly well, except for having to manually screenshot the permissions before the restore and then reapply them from the image taken.
Is there an easy way to use T-SQL to store CURRENT permissions for a user BEFORE the database restore and then reapply those same permissions once the restoration is complete?
Upvotes: 3
Views: 24441
Reputation: 21
Here is a modified version of the script @Fabian wrote so that I could also script out the permissions for stored procedures. Also adds QUOTENAME so the appropriate things are in brackets.
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
Upvotes: 2
Reputation: 348
The answer to your question is most probably the one from Jeff.
But the script from Howard is very practical, i just added a column, which generates the TSQL Syntax with the information. You can copy that and run as SQL to 'replicate' permissions to another db.
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
Upvotes: 3
Reputation: 1059
Combine this with the answer regarding permissions:
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
Upvotes: 0
Reputation: 1348
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
Upvotes: 1
Reputation: 7484
The problem you are dealing with is known as orphaned users.
Here's a script I've used in the past (I had to put this together from memory to you should verify it carefully):
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', @UserNamePattern=@UserName, @LoginName=@UserName;
end
close mycursor;
deallocate mycursor;
This script makes one important assumption. That the users login name and their user name in the database match. If that isn't true, you will have to change the @LoginName parameter sent to sp_change_users_login.
Upvotes: 0
Reputation: 13141
There's a very useful function: sys.fn_my_permissions ( securable , 'securable_class' ) It enables you to see EFFECTICVE permissions of current user to specified objects, so I don't know if you can simply build GRANT/DENY commands from it. I never used it that way. In your case you'd run it as another user:
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
Upvotes: 1