我需要制作一个脚本,将一个特定的数据库角色从一个SQL服务器复制到另一个SQL服务器。
是否有一种简单的方法可以生成创建角色和所有角色权限的脚本?
答案 0 :(得分:26)
您可以使用以下脚本获得所需内容:
declare @RoleName varchar(50) = 'RoleName'
declare @Script varchar(max) = 'CREATE ROLE ' + @RoleName + char(13)
select @script = @script + 'GRANT ' + prm.permission_name + ' ON ' + OBJECT_NAME(major_id) + ' TO ' + rol.name + char(13) COLLATE Latin1_General_CI_AS
from sys.database_permissions prm
join sys.database_principals rol on
prm.grantee_principal_id = rol.principal_id
where rol.name = @RoleName
print @script
答案 1 :(得分:7)
我扩展了Mario Eis的答案:
SELECT 'GRANT ' + database_permissions.permission_name + ' ON ' + CASE database_permissions.class_desc
WHEN 'SCHEMA'
THEN '[' + schema_name(major_id) + ']'
WHEN 'OBJECT_OR_COLUMN'
THEN CASE
WHEN minor_id = 0
THEN'['+OBJECT_SCHEMA_NAME(major_id) + '].' + '[' + object_name(major_id) + ']' COLLATE Latin1_General_CI_AS_KS_WS
ELSE (
SELECT object_name(object_id) + ' (' + NAME + ')'
FROM sys.columns
WHERE object_id = database_permissions.major_id
AND column_id = database_permissions.minor_id
)
END
ELSE 'other'
END + ' TO [' + database_principals.NAME + ']' COLLATE Latin1_General_CI_AS_KS_WS
FROM sys.database_permissions
JOIN sys.database_principals ON database_permissions.grantee_principal_id = database_principals.principal_id
LEFT JOIN sys.objects --left because it is possible that it is a schema
ON objects.object_id = database_permissions.major_id
WHERE database_permissions.major_id > 0
AND permission_name IN (
'SELECT'
,'INSERT'
,'UPDATE'
,'DELETE'
,'EXECUTE'
)
答案 2 :(得分:4)
此脚本为您的角色生成GRANT语句。我喜欢,它支持列leven权限。它必须适应您的需要(即改进更复杂的数据库,连接语句和执行,包括您的角色的create语句)。但只是为了给你一个想法:
SELECT 'GRANT ' + database_permissions.permission_name + ' ON ' +
CASE database_permissions.class_desc
WHEN 'SCHEMA' THEN schema_name(major_id)
WHEN 'OBJECT_OR_COLUMN' THEN
CASE WHEN minor_id = 0 THEN object_name(major_id) COLLATE Latin1_General_CI_AS_KS_WS
ELSE (SELECT object_name(object_id) + ' ('+ name + ')'
FROM sys.columns
WHERE object_id = database_permissions.major_id
AND column_id = database_permissions.minor_id) end
ELSE 'other'
END +
' TO ' + database_principals.name COLLATE Latin1_General_CI_AS_KS_WS
FROM sys.database_permissions
JOIN sys.database_principals
ON database_permissions.grantee_principal_id = database_principals.principal_id
LEFT JOIN sys.objects --left because it is possible that it is a schema
ON objects.object_id = database_permissions.major_id
WHERE database_permissions.major_id > 0
AND permission_name in ('SELECT','INSERT','UPDATE','DELETE')
答案 3 :(得分:3)
在SSMS中右键单击用户/登录/角色节点并选择“脚本为”将编写此特定用户/登录/角色的脚本。但是你不能用这种方式编写角色。{/ p> 带有“数据库开发”选项的{p> Visual Studio和Red Gate SQL Compare可以生成数据库之间的更改脚本,包括用户,角色和角色成员资格。
由VS角色成员资格生成如下所示:
EXECUTE sp_addrolemember @rolename = N'db_datareader', @membername = N'DOMAIN\User';
如果你没有VS,你可以手动编写,也可以创建一个sql脚本来生成它们。
我确信还应该有一个免费的工具来做这样的事情,但由于我不需要它,因为我有Visual Studio,我从来没有找过它。
编辑:我刚刚意识到我正在回答一个错误的问题,你问的是角色权限,我告诉你有关角色成员资格的问题。为此表示歉意。我会在这里留下这个答案,以防它对其他人有用。 Alex Aza的回答看起来不错。
答案 4 :(得分:3)
我制作了一个非常全面的脚本,不仅编写了所有权限的脚本,还编写了所有成员资格,并将蛋糕上的结霜格式化为输出,以便轻松复制/粘贴到新的查询窗口中。我已将脚本发布到my blog并不时更新,但以下版本应涵盖大多数基础:
/********************************************************************
* *
* Author: John Eisbrener *
* Script Purpose: Script out Database Role Definition *
* Notes: Please report any bugs to http://www.dbaeyes.com/ *
* *
********************************************************************/
DECLARE @roleName VARCHAR(255)
SET @roleName = 'DatabaseRoleName'
-- Script out the Role
DECLARE @roleDesc VARCHAR(MAX), @crlf VARCHAR(2)
SET @crlf = CHAR(13) + CHAR(10)
SET @roleDesc = 'CREATE ROLE [' + @roleName + ']' + @crlf + 'GO' + @crlf + @crlf
SELECT @roleDesc = @roleDesc +
CASE dp.state
WHEN 'D' THEN 'DENY '
WHEN 'G' THEN 'GRANT '
WHEN 'R' THEN 'REVOKE '
WHEN 'W' THEN 'GRANT '
END +
dp.permission_name + ' ' +
CASE dp.class
WHEN 0 THEN ''
WHEN 1 THEN --table or column subset on the table
CASE WHEN dp.major_id < 0 THEN
+ 'ON [sys].[' + OBJECT_NAME(dp.major_id) + '] '
ELSE
+ 'ON [' +
(SELECT SCHEMA_NAME(schema_id) + '].[' + name FROM sys.objects WHERE object_id = dp.major_id)
+ -- optionally concatenate column names
CASE WHEN MAX(dp.minor_id) > 0
THEN '] ([' + REPLACE(
(SELECT name + '], ['
FROM sys.columns
WHERE object_id = dp.major_id
AND column_id IN (SELECT minor_id
FROM sys.database_permissions
WHERE major_id = dp.major_id
AND USER_NAME(grantee_principal_id) IN (@roleName)
)
FOR XML PATH('')
) --replace final square bracket pair
+ '])', ', []', '')
ELSE ']'
END + ' '
END
WHEN 3 THEN 'ON SCHEMA::[' + SCHEMA_NAME(dp.major_id) + '] '
WHEN 4 THEN 'ON ' + (SELECT RIGHT(type_desc, 4) + '::[' + name FROM sys.database_principals WHERE principal_id = dp.major_id) + '] '
WHEN 5 THEN 'ON ASSEMBLY::[' + (SELECT name FROM sys.assemblies WHERE assembly_id = dp.major_id) + '] '
WHEN 6 THEN 'ON TYPE::[' + (SELECT name FROM sys.types WHERE user_type_id = dp.major_id) + '] '
WHEN 10 THEN 'ON XML SCHEMA COLLECTION::[' + (SELECT SCHEMA_NAME(schema_id) + '.' + name FROM sys.xml_schema_collections WHERE xml_collection_id = dp.major_id) + '] '
WHEN 15 THEN 'ON MESSAGE TYPE::[' + (SELECT name FROM sys.service_message_types WHERE message_type_id = dp.major_id) + '] '
WHEN 16 THEN 'ON CONTRACT::[' + (SELECT name FROM sys.service_contracts WHERE service_contract_id = dp.major_id) + '] '
WHEN 17 THEN 'ON SERVICE::[' + (SELECT name FROM sys.services WHERE service_id = dp.major_id) + '] '
WHEN 18 THEN 'ON REMOTE SERVICE BINDING::[' + (SELECT name FROM sys.remote_service_bindings WHERE remote_service_binding_id = dp.major_id) + '] '
WHEN 19 THEN 'ON ROUTE::[' + (SELECT name FROM sys.routes WHERE route_id = dp.major_id) + '] '
WHEN 23 THEN 'ON FULLTEXT CATALOG::[' + (SELECT name FROM sys.fulltext_catalogs WHERE fulltext_catalog_id = dp.major_id) + '] '
WHEN 24 THEN 'ON SYMMETRIC KEY::[' + (SELECT name FROM sys.symmetric_keys WHERE symmetric_key_id = dp.major_id) + '] '
WHEN 25 THEN 'ON CERTIFICATE::[' + (SELECT name FROM sys.certificates WHERE certificate_id = dp.major_id) + '] '
WHEN 26 THEN 'ON ASYMMETRIC KEY::[' + (SELECT name FROM sys.asymmetric_keys WHERE asymmetric_key_id = dp.major_id) + '] '
END COLLATE SQL_Latin1_General_CP1_CI_AS
+ 'TO [' + @roleName + ']' +
CASE dp.state WHEN 'W' THEN ' WITH GRANT OPTION' ELSE '' END + @crlf
FROM sys.database_permissions dp
WHERE USER_NAME(dp.grantee_principal_id) IN (@roleName)
GROUP BY dp.state, dp.major_id, dp.permission_name, dp.class
SELECT @roleDesc = @roleDesc + 'GO' + @crlf + @crlf
-- Display users within Role. Code stubbed by Joe Spivey
SELECT @roleDesc = @roleDesc + 'EXECUTE sp_AddRoleMember ''' + roles.name + ''', ''' + users.name + '''' + @crlf
FROM sys.database_principals users
INNER JOIN sys.database_role_members link
ON link.member_principal_id = users.principal_id
INNER JOIN sys.database_principals roles
ON roles.principal_id = link.role_principal_id
WHERE roles.name = @roleName
-- PRINT out in blocks of up to 8000 based on last \r\n
DECLARE @printCur INT
SET @printCur = 8000
WHILE LEN(@roleDesc) > 8000
BEGIN
-- Reverse first 8000 characters and look for first lf cr (reversed crlf) as delimiter
SET @printCur = 8000 - CHARINDEX(CHAR(10) + CHAR(13), REVERSE(SUBSTRING(@roleDesc, 0, 8000)))
PRINT LEFT(@roleDesc, @printCur)
SELECT @roleDesc = RIGHT(@roleDesc, LEN(@roleDesc) - @printCur)
END
PRINT @RoleDesc + 'GO'
值得注意的是,您可能会遇到sp_AddRoleMember系统sp将用户添加到之前不存在的DB的情况。在这种情况下,即使添加了用户,也不会授予他们CONNECT权限,并且所述用户或组所做的任何连接尝试都将产生用户登录错误。要解决此问题,您需要在db中执行以下每个新用户/组:
USE [DatabaseName]
GO
GRANT CONNECT TO [Login/GroupName]
GO
答案 5 :(得分:0)
这很痛苦,但您要查找的所有内容都在几个系统视图中:sys.database_permissions,sys.database_principals和sys.database_role_members。它不是一个款待的原因是因为sys.database_permissions中的major_id和minor_id具有基于类列的不同含义。但是如果你的权限相对简单,那么这可能不会那么糟糕。看一看,看看你能得到什么。
答案 6 :(得分:0)
-- Use this if you have a lot of permissions assigned to a Database Role
-- Before running, set results to Text
SET NOCOUNT ON
Use MyDB; -- CHANGE DATABASE NAME
DECLARE @RoleName varchar(50) = 'sp_exec' --- change role name here
SELECT 'CREATE ROLE [' + @RoleName + '];'+ char(13)
SELECT 'GRANT ' + prm.permission_name + ' ON [' +
OBJECT_NAME(major_id) + '] TO [' + rol.name + '] ;' + char(13) COLLATE Latin1_General_CI_AS
from sys.database_permissions prm
join sys.database_principals rol on
prm.grantee_principal_id = rol.principal_id
where rol.name = @RoleName
答案 7 :(得分:-1)
我在上面的代码中添加了一个额外的脚本功能。 select脚本输出角色和权限,因此您只需要执行结果:
-- Update the RoleName with the name of your role
DECLARE @RoleName VARCHAR(75) = 'RoleName'
DECLARE @RoleTable TABLE ([GrantedBy] VARCHAR (50) NOT NULL, [Permission] VARCHAR (50) NOT NULL, [State] VARCHAR (50) NOT NULL)
DECLARE @RoleScript VARCHAR(75)
INSERT INTO @RoleTable SELECT p2.[name], dbp.[permission_name], dbp.[state_desc]
FROM [sys].[database_permissions] dbp LEFT JOIN [sys].[objects] so
ON dbp.[major_id] = so.[object_id] LEFT JOIN [sys].[database_principals] p
ON dbp.[grantee_principal_id] = p.[principal_id] LEFT JOIN [sys].[database_principals] p2
ON dbp.[grantor_principal_id] = p2.[principal_id]
WHERE p.[name] = @RoleName
SELECT 'USE [' + DB_NAME() + '] CREATE ROLE [' + @RoleName + ']' AS 'Create Role'
SELECT 'USE [' + DB_NAME() + '] GRANT ' + [Permission] + ' ON SCHEMA::[' + [GrantedBy] + '] TO [' + @RoleName + ']' AS 'Add Permissions'
FROM @RoleTable