编写SQL Server权限脚本

Chr*_*eld 42 sql-server

我想将我在存储过程和其他内容上设置的所有权限从我的开发数据库复制到我的生产数据库.通过SSMS GUI工具手动执行此操作非常麻烦,更不用说容易出错了.

所以我正在寻找一种方法可以直接转储在一个数据库中设置的权限,并将这些相同的权限应用于单独的数据库(可能具有相同的模式).

Chr*_*eld 73

数据库的内置目录视图提供了执行此操作的信息.试试这个查询:

SELECT
  (
    dp.state_desc + ' ' +
    dp.permission_name collate latin1_general_cs_as + 
    ' ON ' + '[' + s.name + ']' + '.' + '[' + o.name + ']' +
    ' TO ' + '[' + dpr.name + ']'
  ) AS GRANT_STMT
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
WHERE dpr.name NOT IN ('public','guest')
--  AND o.name IN ('My_Procedure')      -- Uncomment to filter to specific object(s)
--  AND dp.permission_name='EXECUTE'    -- Uncomment to filter to just the EXECUTEs
Run Code Online (Sandbox Code Playgroud)

这将为数据库中的每个权限吐出一堆命令(GRANT/DENY).从这里,您可以将它们复制并粘贴到另一个查询窗口并执行,以生成原始版本上相同的权限.例如:

GRANT EXECUTE ON [Exposed].[EmployeePunchoutReservationRetrieve] TO [CustomerAgentRole]
GRANT EXECUTE ON [Exposed].[EmployeePunchoutReservationStore] TO [CustomerAgentRole]
GRANT EXECUTE ON [Exposed].[EmployeePunchoutSendOrderLogStore] TO [CustomerAgentRole]
GRANT EXECUTE ON [Exposed].[EmployeeReportSubscriptions] TO [CustomerAgentRole]
Run Code Online (Sandbox Code Playgroud)

请注意,底线是注释掉的,即对permission_name进行过滤.取消注释该行将导致查询仅吐出EXECUTE权限(即存储过程的权限).

  • 这个脚本将DENY变为GRANT.你需要将''GRANT''部分改成'dp.state_desc +''`.在s.name,o.name和dpr.name周围添加`QUOTENAME()`也会极大地帮助这个脚本. (10认同)
  • 当您授予或拒绝数据库上的整个 DML 操作时,此脚本将丢失,例如 GRANT SELECT TO [USerName] (2认同)
  • @Matt在/sf/answers/3353462871/的回答中有相同的问题如此修改 (2认同)

Pet*_*iFi 47

您可以让SQL Server Management Studio为您执行此操作:

  • 右键单击要导出权限的数据库
  • 选择"任务",然后选择"生成脚本..."
  • 确认您正在编写脚本的数据库
  • 设置以下脚本选项:
    • 脚本创建:FALSE
    • 脚本对象级权限:TRUE
  • 选择要编写其脚本权限的对象类型
  • 选择要编写其脚本权限的对象
  • 选择您希望脚本生成的位置

这将生成一个脚本来为所有选定对象设置权限,但会抑制对象脚本本身.

这基于MS SQL 2008的对话框,其中所有其他脚本选项与安装默认值相同.

  • 这基于SQL 2008,如果您使用的是较新版本,则可能需要使用其中一种脚本方法,因为它们似乎已从对话框中删除了此选项.我刚刚在2012年尝试过它现在迫使你生成Create语句.如果你正在使用2008只是仔细检查你将"脚本创建"设置为FALSE,因为这将抑制实际的对象脚本. (3认同)
  • 可以通过打开工具 - 选项 - SQL Server对象资源管理器 - 脚本来更改步骤4中选项的默认值. (2认同)
  • 这是我所做的,但它包含太多,它生成表,或sprocs和东西我纯粹想要的权限,似乎无法隔离权限与任务:/ (2认同)
  • @PeteWiFi;我无法让它与新的 SSMS(版本 17.9.1)一起使用。你知道还有可能吗? (2认同)
  • 我的选项不允许脚本创建:False。我的选项是“脚本创建”、“脚本删除”或“脚本删除并创建”。因此,我只能生成包含所有对象的权限和创建的脚本,这不是我想要的。使用 SSMS 17.9.1 (2认同)

Mad*_*avn 8

扩展/sf/answers/139105081/中提供的答案,对于数据库/架构范围的权限和您可以使用的数据库用户类型,此答案失败:

SELECT
  CASE
      WHEN dp.class_desc = 'OBJECT_OR_COLUMN' THEN
        dp.state_desc + ' ' + dp.permission_name collate latin1_general_cs_as + 
        ' ON ' + '[' + obj_sch.name + ']' + '.' + '[' + o.name + ']' +
        ' TO ' + '[' + dpr.name + ']'
      WHEN dp.class_desc = 'DATABASE' THEN
        dp.state_desc + ' ' + dp.permission_name collate latin1_general_cs_as + 
        ' TO ' + '[' + dpr.name + ']'
      WHEN dp.class_desc = 'SCHEMA' THEN
        dp.state_desc + ' ' + dp.permission_name collate latin1_general_cs_as + 
        ' ON SCHEMA :: ' + '[' + SCHEMA_NAME(dp.major_id) + ']' +
        ' TO ' + '[' + dpr.name + ']'
      WHEN dp.class_desc = 'TYPE' THEN
        dp.state_desc + ' ' + dp.permission_name collate Latin1_General_CS_AS + 
        ' ON TYPE :: [' + s_types.name + '].[' + t.name + ']'
            + ' TO [' + dpr.name + ']'
      WHEN dp.class_desc = 'CERTIFICATE' THEN 
        dp.state_desc + ' ' + dp.permission_name collate latin1_general_cs_as + 
        ' TO ' + '[' + dpr.name + ']' 
      WHEN dp.class_desc = 'SYMMETRIC_KEYS' THEN 
        dp.state_desc + ' ' + dp.permission_name collate latin1_general_cs_as + 
      ' TO ' + '[' + dpr.name + ']' 
      ELSE 
        'ERROR: Unhandled class_desc: ' + dp.class_desc
  END
 AS GRANT_STMT
FROM sys.database_permissions AS dp 
  JOIN sys.database_principals AS dpr ON dp.grantee_principal_id=dpr.principal_id
  LEFT JOIN sys.objects AS o ON dp.major_id=o.object_id
  LEFT JOIN sys.schemas AS obj_sch ON o.schema_id = obj_sch.schema_id
  LEFT JOIN sys.types AS t ON dp.major_id = t.user_type_id
  LEFT JOIN sys.schemas AS s_types ON t.schema_id = s_types.schema_id
WHERE 
dpr.name NOT IN ('public','guest') 
--  AND o.name IN ('My_Procedure')      -- Uncomment to filter to specific object(s)
--  AND (o.name NOT IN ('My_Procedure') or o.name is null)  -- Uncomment to filter out specific object(s), but include rows with no o.name (VIEW DEFINITION etc.)
--  AND dp.permission_name='EXECUTE'    -- Uncomment to filter to just the EXECUTEs
--  AND dpr.name LIKE '%user_name%'     -- Uncomment to filter to just matching users
ORDER BY dpr.name, dp.class_desc, dp.permission_name
Run Code Online (Sandbox Code Playgroud)

  • 模式级别权限授予的格式不正确:`GRANT UPDATE ON SCHEMA [test] TO [TestUser]` 而不是:`GRANT UPDATE ON SCHEMA :: [test] TO [TestUser]` 否则,答案很棒! (2认同)
  • @Chris:感谢更新了答案以生成正确的SQL。 (2认同)
  • 我遇到的另一个问题是架构所有者的架构未转移。架构所有者对其拥有的表具有完全访问权限。要查找现有架构所有者:`SELECT schema_name, schema_owner FROM information_schema.schemata` 然后将它们分配到新数据库上。`ALTER AUTHORIZATION ON SCHEMA::SCHEMA_NAME_HERE TO DB_USER_NAME_HERE` [Mirosoft 有关 ALTER AUTHORIZATION 语法的文档。](https://learn.microsoft.com/en-us/sql/t-sql/statements/alter-authorization-transact -sql?view=sql-server-2017) (2认同)
  • @MadsRavn; 我也有一个证书和一个对称密钥,这会导致例外,除非您添加:当dp.class_desc ='CERTIFICATE'THEN dp.state_desc +''+ dp.permission_name整理latin1_general_cs_as +'TO'+'['+ dpr.name +']'dp.class_desc ='SYMMETRIC_KEYS'则dp.state_desc +''+ dp.permission_name整理latin1_general_cs_as +'TO'+'['+ dpr.name +']' (2认同)
  • @Henrik Staun Poulsen 谢谢 - 更新了您的建议。 (2认同)

gbn*_*gbn 5

是的,您可以使用这样的脚本生成另一个脚本

SET NOCOUNT ON;
DECLARE @NewRole varchar(100), @SourceRole varchar(100);

-- Change as needed
SELECT @SourceRole = 'Giver', @NewRole = 'Taker';

SELECT
    state_desc + ' ' + permission_name + ' ON ' + OBJECT_NAME(major_id) + ' TO ' + @NewRole
FROM
    sys.database_permissions
WHERE
    grantee_principal_id = DATABASE_PRINCIPAL_ID(@SourceRole) AND
    -- 0 = DB,  1 = object/column, 3 = schema. 1 is normally enough
    class <= 3
Run Code Online (Sandbox Code Playgroud)

这取自我在这里的回答