用于列出所有现有数据库和用户的SQL查询

时间:2014-06-17 08:34:49

标签: sql-server-2008

我需要在一个表中查找SQL查询:

  • 所有现有数据库。
  • 每个数据库的所有用户及其角色。

我尝试使用以下查询列出数据库角色,但我只得到一个数据库的结果。

select
  rp.name as database_role,
  mp.name as database_user
from
  sys.database_role_members drm
  join sys.database_principals rp
    on (drm.role_principal_id = rp.principal_id)
  join sys.database_principals mp
    on (drm.member_principal_id = mp.principal_id)

1 个答案:

答案 0 :(得分:0)

您获得了当前数据库的结果,因为这是目录视图的工作方式。另一方面,您可以使用由三部分组成的名称来查询其他数据库的目录视图。

例如,如果要从msdb数据库中选择表,可以使用以下语法:

SELECT * FROM msdb.sys.tables

查询所有数据库

下一个问题是为所有数据库编写查询。不幸的是,没有“所有数据库”的参考,但是有一个无证的存储过程可以提供帮助。这是sp_MSforeachdb

请注意,短语undocumented表示实现和参数列表可能会更改,或者可以随时删除该功能,因此在使用任何未记录的功能时要小心! / em>的

列出所有角色的查询如下所示:

EXEC sp_MSforeachdb
    @command1 = '
        INSERT INTO ##RoleTemp (db, database_role, database_user)
        SELECT
            ''?'' AS db,
            rp.NAME AS database_role,
            mp.NAME AS database_user
        FROM
            [?].sys.database_role_members drm
            INNER JOIN [?].sys.database_principals rp
                ON (drm.role_principal_id = rp.principal_id)
            INNER JOIN [?].sys.database_principals mp
                ON (drm.member_principal_id = mp.principal_id);
    '

SP将遍历所有数据库并运行每个数据库的查询。上述查询中的问号将替换为实际的数据库名称。

合并数据集

此查询存在一个小问题:它将返回多个结果(每个数据库一个结果)。

最后一步是将所有结果合并为一个结果。 sp_MSforeachdb的参数多于上面的参数。要解决多结果问题,您可以使用@precommand@postcommand参数。

@precommand参数提供的查询只会在主查询之前运行一次,而@postcommand将在结束时运行。

知道这一点,最终的查询将是:

EXEC sp_MSforeachdb
    @precommand = N'CREATE TABLE ##RoleTemp (db VARCHAR(MAX), database_role VARCHAR(MAX), database_user VARCHAR(MAX));',
    @command1 = '
        INSERT INTO ##RoleTemp (db, database_role, database_user)
        SELECT
            ''?'' AS db,
            rp.NAME AS database_role,
            mp.NAME AS database_user
        FROM
            [?].sys.database_role_members drm
            INNER JOIN [?].sys.database_principals rp
                ON (drm.role_principal_id = rp.principal_id)
            INNER JOIN [?].sys.database_principals mp
                ON (drm.member_principal_id = mp.principal_id);
    ',
    @postcommand = 'SELECT * FROM ##RoleTemp; DROP TABLE ##RoleTemp;'

这将创建一个临时表,然后将所有数据库中的所有结果插入到该临时表中。 post命令选择插入临时表的所有记录,然后删除临时表。

我希望,这有助于解决您的问题。