如何在单个结果集中列出SQL Server中所有数据库中的所有表?

Mic*_*ens 61 sql-server metadata

我正在寻找T-SQL代码来列出SQL Server中所有数据库中的所有表(至少在SS2005和SS2008中;最好也适用于SS2000).然而,问题是,我想要一个结果集.这排除了Pinal Dave的优秀答案:

sp_msforeachdb 'select "?" AS db, * from [?].sys.tables'
Run Code Online (Sandbox Code Playgroud)

上面的存储过程为每个数据库生成一个结果集,如果你在像SSMS这样可以显示多个结果集的IDE中,这很好.但是,我想要一个结果集,因为我想要一个本质上是"查找"工具的查询:如果我添加一个像这样的子句,WHERE tablename like '%accounts'它会告诉我在哪里可以找到我的BillAccounts,ClientAccounts和VendorAccounts表,无论它们驻留在哪个数据库中在.


2010.05.20更新,约20分钟后......

到目前为止,Remus的回答看起来最有趣.我发布了一个版本的修改版本,包括数据库名称和示例过滤器子句,而不是将其作为答案发布并将其授予自己.看起来Remus会在这一点上获得答案!

declare @sql nvarchar(max);
set @sql = N'select b.name as "DB", a.name collate Latin1_General_CI_AI as "Table", object_id, schema_id, cast(1 as int) as database_id  from master.sys.tables a join sys.databases b on database_id=1 where a.name like ''account%''';

select @sql = @sql + N' union all select b.name as "DB", a.name collate Latin1_General_CI_AI, object_id, schema_id, ' + cast(database_id as nvarchar(10)) + N' from ' + quotename(name) + N'.sys.tables a join sys.databases b on database_id=' + cast(database_id as nvarchar(10)) + 'where a.name like ''account%'''
from sys.databases where database_id > 1 

and state = 0
and user_access = 0;

exec sp_executesql @sql;
Run Code Online (Sandbox Code Playgroud)

2010.05.24更新 - 新的领跑者!

反馈和答案都很棒.持续的合作参与导致了一个新的领跑者:KM从5月21日开始的回答!

以下是我用Remus解决方案发现的问题:

主要问题:用户具有不同的权限,这使得查询基于数据(即过滤值)成功.在没有过滤的情况下在我的生产数据库上运行(即省略该WHERE子句)我在几个我无权访问的数据库上收到此错误:

服务器主体"msorens"无法访问当前安全上下文下的数据库"ETLprocDB".

查询成功使用一些过滤子句 - 那些不接触访问级别之外的DB的过滤子句.

小问题:不容易降级到SQL Server 2000支持(是的,我们还有一些人在那里使用它......)因为它在为每个数据库累积条目时构建一个字符串.使用我的系统,我在大约40个数据库中超过了8000个字符.

次要问题:重复代码 - 循环设置基本上复制了循环体.我理解其基本原理,但这只是我的一个宠儿......

KM的答案不受这些问题的影响.存储sp_msforeachdb过程会考虑用户的权限,因此可以避免权限问题.我还没有尝试使用SS2000的代码,但KM表示应该进行调整.

我根据个人喜好发布我对KM答案的修改.特别:

  • 我删除了服务器名称,因为它没有在结果集中添加任何内容.
  • 我已将名称组件拆分为结果集中的各自字段(数据库名称,模式名称和表名称).
  • 我为这三个字段中的每一个引入了单独的过滤器.
  • 我已经添加了三个字段的排序(可以根据您的喜好进行修改).

以下是我对KM代码的修改(仅对表名应用了一个示例过滤器):

SET NOCOUNT ON
DECLARE @AllTables table (DbName sysname,SchemaName sysname, TableName sysname)
DECLARE
     @SearchDb nvarchar(200)
    ,@SearchSchema nvarchar(200)
    ,@SearchTable nvarchar(200)
    ,@SQL nvarchar(4000)
SET @SearchDb='%'
SET @SearchSchema='%'
SET @SearchTable='%Account%'
SET @SQL='select ''?'' as DbName, s.name as SchemaName, t.name as TableName from [?].sys.tables t inner join sys.schemas s on t.schema_id=s.schema_id WHERE ''?'' LIKE '''+@SearchDb+''' AND s.name LIKE '''+@SearchSchema+''' AND t.name LIKE '''+@SearchTable+''''

INSERT INTO @AllTables (DbName, SchemaName, TableName)
    EXEC sp_msforeachdb @SQL
SET NOCOUNT OFF
SELECT * FROM @AllTables ORDER BY DbName, SchemaName, TableName
Run Code Online (Sandbox Code Playgroud)

KM.*_*KM. 37

要获得服务器上所有表的简单方法,请尝试以下方法:

SET NOCOUNT ON
DECLARE @AllTables table (CompleteTableName nvarchar(4000))
INSERT INTO @AllTables (CompleteTableName)
    EXEC sp_msforeachdb 'select @@SERVERNAME+''.''+''?''+''.''+s.name+''.''+t.name from [?].sys.tables t inner join sys.schemas s on t.schema_id=s.schema_id'
SET NOCOUNT OFF
SELECT * FROM @AllTables ORDER BY 1
Run Code Online (Sandbox Code Playgroud)

它将返回包含服务器+数据库+模式+表名的单个列:示例输出:

CompleteTableName
--------------------------------------------
YourServer.YourDatabase1.YourSchema1.YourTable1
YourServer.YourDatabase1.YourSchema1.YourTable2
YourServer.YourDatabase1.YourSchema2.YourTable1
YourServer.YourDatabase1.YourSchema2.YourTable2
YourServer.YourDatabase2.YourSchema1.YourTable1
Run Code Online (Sandbox Code Playgroud)

如果你不是SQL Server 2005或高达上,更换DECLARE @AllTables tableCREATE TABLE #AllTables,然后每@AllTables#AllTables,它会工作.


这里的EDIT是一个允许在服务器+数据库+模式+表名的任何部分或部分上使用搜索参数的版本:

SET NOCOUNT ON
DECLARE @AllTables table (CompleteTableName nvarchar(4000))
DECLARE @Search nvarchar(4000)
       ,@SQL   nvarchar(4000)
SET @Search=null --all rows
SET @SQL='select @@SERVERNAME+''.''+''?''+''.''+s.name+''.''+t.name from [?].sys.tables t inner join sys.schemas s on t.schema_id=s.schema_id WHERE @@SERVERNAME+''.''+''?''+''.''+s.name+''.''+t.name LIKE ''%'+ISNULL(@SEARCH,'')+'%'''

INSERT INTO @AllTables (CompleteTableName)
    EXEC sp_msforeachdb @SQL
SET NOCOUNT OFF
SELECT * FROM @AllTables ORDER BY 1
Run Code Online (Sandbox Code Playgroud)

将@Search设置为所有表的NULL,将其设置为'dbo.users'或'users'或'.master.dbo'之类的内容,甚至包括'.master.%.u'等通配符.

  • 替换这一行:`SET @SQL='select @@SERVERNAME+''.''+''?''+''.''+s.name+''.''+t.name from [?]。 .sysobjects tinner join sysusers on t.uid=s.uid WHERE @@SERVERNAME+''.''+''?''+''.''+s.name+''.''+t.name LIKE ''%'+ISNULL(@SEARCH,'')+'%'''` (2认同)

Rem*_*anu 14

declare @sql nvarchar(max);
set @sql = N'select cast(''master'' as sysname) as db_name, name collate Latin1_General_CI_AI, object_id, schema_id, cast(1 as int) as database_id  from master.sys.tables ';

select @sql = @sql + N' union all select ' + quotename(name,'''')+ ', name collate Latin1_General_CI_AI, object_id, schema_id, ' + cast(database_id as nvarchar(10)) + N' from ' + quotename(name) + N'.sys.tables'
from sys.databases where database_id > 1
and state = 0
and user_access = 0;

exec sp_executesql @sql;
Run Code Online (Sandbox Code Playgroud)


Joh*_*ohn 9

我需要一些东西,我可以使用CMS搜索我的所有服务器,并按服务器,数据库,模式或表搜索.这是我发现的(最初由Michael Sorens在这里发布:如何在单个结果集中列出SQL Server中所有数据库中的所有表?).

SET NOCOUNT ON
DECLARE @AllTables TABLE
        (
         ServerName NVARCHAR(200)
        ,DBName NVARCHAR(200)
        ,SchemaName NVARCHAR(200)
        ,TableName NVARCHAR(200)
        )
DECLARE @SearchSvr NVARCHAR(200)
       ,@SearchDB NVARCHAR(200)
       ,@SearchS NVARCHAR(200)
       ,@SearchTbl NVARCHAR(200)
       ,@SQL NVARCHAR(4000)

SET @SearchSvr = NULL  --Search for Servers, NULL for all Servers
SET @SearchDB = NULL  --Search for DB, NULL for all Databases
SET @SearchS = NULL  --Search for Schemas, NULL for all Schemas
SET @SearchTbl = NULL  --Search for Tables, NULL for all Tables

SET @SQL = 'SELECT @@SERVERNAME
        ,''?''
        ,s.name
        ,t.name
         FROM [?].sys.tables t 
         JOIN sys.schemas s on t.schema_id=s.schema_id 
         WHERE @@SERVERNAME LIKE ''%' + ISNULL(@SearchSvr, '') + '%''
         AND ''?'' LIKE ''%' + ISNULL(@SearchDB, '') + '%''
         AND s.name LIKE ''%' + ISNULL(@SearchS, '') + '%''
         AND t.name LIKE ''%' + ISNULL(@SearchTbl, '') + '%''
      -- AND ''?'' NOT IN (''master'',''model'',''msdb'',''tempdb'',''SSISDB'')
           '
-- Remove the '--' from the last statement in the WHERE clause to exclude system tables

INSERT  INTO @AllTables
        (
         ServerName
        ,DBName
        ,SchemaName
        ,TableName
        )
        EXEC sp_MSforeachdb @SQL
SET NOCOUNT OFF
SELECT  *
FROM    @AllTables
ORDER BY 1,2,3,4
Run Code Online (Sandbox Code Playgroud)