查看数据库图表所需的权限

Ste*_*eve 11 sql-server permissions sql-server-2012

我最近设置了 SSDT 供我们的开发人员使用。我们通过 SSDT 通过限制每个开发人员在连接到服务器(db_datareader、db_datawriter)时拥有的权限来强制更改我们的开发数据库。在 SSDT 中,我们使用部署脚本将更改发布到数据库,该脚本使用具有提升权限的登录进行连接。

我的问题。鉴于我们已经走到了这个长度来锁定数据库(以阻止模式漂移);有没有什么方法可以让开发人员在没有 db_owner 权限的情况下查看这个数据库上的图表?我知道每个开发人员都可以创建和查看他或她自己的图表,但我希望他们能够查看由许多不同开发人员创建的所有图表。

我不认为这会有所帮助,但我们正在运行 sql server 2012

任何帮助都会得到很大的帮助。

Aar*_*and 17

文档

  • 尽管有权访问数据库的任何用户都可以创建图表,但是一旦创建了图表,唯一可以看到它的用户就是图表的创建者和 db_owner 角色的任何成员。
  • 图表的所有权只能转让给 db_owner 角色的成员。仅当图表的先前所有者已从数据库中删除时,这才是可能的。
  • 如果图表的所有者已从数据库中删除,则图表将保留在数据库中,直到 db_owner 角色的成员尝试打开它。此时 db_owner 成员可以选择接管图表的所有权。

所以看起来像db_datareader.

在幕后,Management Studio 呼吁推动名单:

CREATE PROCEDURE dbo.sp_helpdiagrams
(
    @diagramname sysname = NULL,
    @owner_id int = NULL
)
WITH EXECUTE AS N'dbo'
AS
BEGIN
    DECLARE @user sysname
    DECLARE @dboLogin bit
    EXECUTE AS CALLER;
        SET @user = USER_NAME();
        SET @dboLogin = CONVERT(bit,IS_MEMBER('db_owner'));
    REVERT;
    SELECT
        [Database] = DB_NAME(),
        [Name] = name,
        [ID] = diagram_id,
        [Owner] = USER_NAME(principal_id),
        [OwnerID] = principal_id
    FROM
        sysdiagrams
    WHERE
        (@dboLogin = 1 OR USER_NAME(principal_id) = @user) AND
        (@diagramname IS NULL OR name = @diagramname) AND
        (@owner_id IS NULL OR principal_id = @owner_id)
    ORDER BY
        4, 5, 1
END
Run Code Online (Sandbox Code Playgroud)

所以你可以看到这与文档匹配。

现在有几个解决方法的想法:

  • 在登录触发器,更新principal_id所有图表是当前登录。这意味着他们将可以访问所有图表,直到下一个人登录。不是最佳选择。
  • sysdiagrams表本身上使用触发器(它不是真正的系统表),并且每当创建或更新图表时,为每个主体添加/更新一个副本(附加他们的用户名)。也不是最优的,你可能会让人们整天覆盖彼此的图表。

这是第二个解决方法的想法 - 您真正需要在这里维护的是您希望能够访问图表的数据库主体列表(您还需要一些东西来清理已删除的图表,以及一些定期维护,删除已删除主体的图表):

CREATE TRIGGER dbo.sysdiagrams_distribute
ON dbo.sysdiagrams
WITH EXECUTE AS N'dbo'
FOR INSERT, UPDATE
AS
BEGIN
  SET NOCOUNT ON;

  DECLARE @p TABLE(principal_id INT, name SYSNAME);

  INSERT @p SELECT principal_id, name
    FROM sys.database_principals
    -- change this list:
    WHERE name IN (N'test_blat_user', N'test_blat_user2', N'dbo');

  UPDATE d 
    SET [version] = i.version, definition = i.definition
  FROM inserted AS i
  CROSS JOIN @p AS p
  INNER JOIN dbo.sysdiagrams AS d
  ON d.name = i.name
  AND d.principal_id = p.principal_id;

  INSERT dbo.sysdiagrams(name, principal_id, version, definition)
    SELECT i.name, p.principal_id, i.version, i.definition
    FROM inserted AS i
    CROSS JOIN @p AS p
    WHERE NOT EXISTS 
    (
      SELECT 1 FROM dbo.sysdiagrams WHERE name = i.name
      AND principal_id = p.principal_id
    );
END
GO
Run Code Online (Sandbox Code Playgroud)

创建几个图表后,以下是这些用户的对象资源管理器的删节版:

在此处输入图片说明

现在,dbo将收集一大堆图表副本,这可能不是必需的,但在大多数情况下,您可能希望它们成为“大师”。