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

我正在寻找 T-SQL 代码列出所有数据库中的所有表在 SQL 服务器(至少在 SS2005和 SS2008; 将是不错的,也适用于 SS2000)。然而,问题是我想要一个 单个结果集。这就排除了 皮纳尔 · 戴夫的另一个绝佳答案:

sp_msforeachdb 'select "?" AS db, * from [?].sys.tables'

上面存储的 proc 生成一个结果集 每个数据库 ,如果您处于能够显示多个结果集的像 SSMS 这样的 IDE 中,这样做是可以的。然而,我想要一个单一的结果集,因为我想要一个本质上是一个“查找”工具的查询: 如果我添加一个像 WHERE tablename like '%accounts'这样的子句,那么它会告诉我在哪里可以找到我的 BillAccount、 ClientAccount 和 VendorAccount 表,而不管它们位于哪个数据库中。


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

到目前为止,莱姆斯的回答看起来最有趣。而不是张贴这个作为一个答案和奖励它给我自己,我在这里张贴它的一个版本,我已经修改,以包括数据库名称和一个示例过滤器子句。看起来莱姆斯将得到答案的荣誉,虽然,在这一点上!

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;

2010.05.24更新——新的领跑者!

反馈和回答非常棒。持续的协作参与导致了 新的领跑者: KM 的答案从5月21日!

Here are the issues I uncovered with Remus' solution:

主要问题: 用户拥有不同的权限,这会导致基于数据(即过滤值)的查询成功。使用 过滤在我的生产数据库上运行(即省略 WHERE子句) ,我在几个没有访问权限的 DBs 上收到了这个错误:

服务器主体“ msoren”无法访问数据库 当前安全上下文下的“ ETLprocDB”。

查询 意志坚强使用一些过滤子句取得了成功——这些子句没有触及访问级别之外的 DBs。

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

Minor issue: Duplicate code--the loop setup essentially duplicates the loop body. I understand the rationale but it is just a pet peeve of mine...

知识管理的答案并没有受到这些问题的影响。存储过程 sp_msforeachdb考虑到用户的权限,因此可以避免权限问题。我还没有尝试与 SS2000的代码,但知识管理表明的调整,应该做到这一点。

接下来我将根据个人喜好对 KM 的回答进行修改,具体如下:

  • 我已经删除了服务器名称,因为它实际上并没有在结果集中添加任何内容。
  • I have split the name components into their own fields in the result set (db name, schema name, and table name).
  • 我已经为这三个字段中的每一个引入了单独的过滤器。
  • 我已经添加了三个字段的排序(可以根据您的首选项进行修改)。

Here is my modification to KM's code (with a sample filter applied just to the table name):

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
135002 次浏览

我确信您必须遍历数据库列表,然后列出每个表。你应该能把他们结合在一起。

不久前我发布了一个 给你的答案,你可以在这里使用。大纲是:

  • 创建临时表
  • 调用 sp _ msForEachDb
  • 对每个数据库运行的查询将数据存储在临时表中
  • 完成后,查询临时表
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;

您所需要做的就是运行 sp _ tables 存储过程

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

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

它将返回一个包含 server + database + schema + table name 的列: sample output:

CompleteTableName
--------------------------------------------
YourServer.YourDatabase1.YourSchema1.YourTable1
YourServer.YourDatabase1.YourSchema1.YourTable2
YourServer.YourDatabase1.YourSchema2.YourTable1
YourServer.YourDatabase1.YourSchema2.YourTable2
YourServer.YourDatabase2.YourSchema1.YourTable1

如果您不在 SQLServer2005或以上,将 DECLARE @AllTables table替换为 CREATE TABLE #AllTables,然后每个 @AllTables替换为 #AllTables,它将工作。

剪辑
这个版本允许在服务器 + 数据库 + 模式 + 表名的任何部分使用搜索参数:

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

将所有表的@Search 设置为 NULL,将其设置为‘ dbo.users’或‘ users’或‘ dbo.users’。或者甚至包括通配符。师父。%.等等。

我需要一些东西,我可以用来搜索我所有的服务器使用 CMS 和搜索服务器,数据库,模式或表。这是我发现的(最初由迈克尔索伦斯张贴在这里: 如何在单个结果集中列出 SQLServer 中所有数据库中的所有表?)。

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

这真的很方便,但是我想要一种方法来显示所有的用户对象,而不仅仅是表,所以我调整了它来使用 sys.object 而不是 sys.tables

SET NOCOUNT ON
DECLARE @AllTables table (DbName sysname,SchemaName sysname, ObjectType char(2), ObjectName sysname)
DECLARE
@SearchDb nvarchar(200)
,@SearchSchema nvarchar(200)
,@SearchObject nvarchar(200)
,@SQL nvarchar(4000)
SET @SearchDb='%'
SET @SearchSchema='%'
SET @SearchObject='%Something%'
SET @SQL='select ''?'' as DbName, s.name as SchemaName, t.type as ObjectType, t.name as ObjectName
from [?].sys.objects t inner join sys.schemas s on t.schema_id=s.schema_id
WHERE t.type in (''FN'',''IF'',''U'',''V'',''P'',''TF'')
AND ''?'' LIKE '''+@SearchDb+'''
AND s.name LIKE '''+@SearchSchema+'''
AND t.name LIKE '''+@SearchObject+''''


INSERT INTO @AllTables (DbName, SchemaName, ObjectType, ObjectName)
EXEC sp_msforeachdb @SQL
SET NOCOUNT OFF
SELECT * FROM @AllTables ORDER BY DbName, SchemaName, ObjectType, ObjectName

因为我可以免费获得数据库名称,所以我非常喜欢使用 INformATION _ SCHEMA。还有——从@KM 的帖子中意识到多个结果集很好地插入了——我想到了:

select top 0 *
into #temp
from INFORMATION_SCHEMA.TABLES


insert into #temp
exec sp_msforeachdb 'select * from [?].INFORMATION_SCHEMA.TABLES'


select * from #temp


drop table #temp

我认为通常的方法是使用 sp_MSforeachdb对每个数据库执行 SELECT * FROM INFORMATION_SCHEMA.TABLES

我在 VS Code 中创建了一个片段,我认为它可能会有所帮助。

质疑

IF OBJECT_ID('tempdb..#alltables', 'U') IS NOT NULL DROP TABLE #alltables;
SELECT * INTO #alltables FROM INFORMATION_SCHEMA.TABLES;
TRUNCATE TABLE #alltables;
EXEC sp_MSforeachdb 'USE [?];INSERT INTO #alltables SELECT * from INFORMATION_SCHEMA.TABLES';
SELECT * FROM #alltables WHERE TABLE_NAME LIKE '%<TABLE_NAME_TO_SEARCH>%';
GO

片段

{
"List all tables": {
"prefix": "sqlListTable",
"body": [
"IF OBJECT_ID('tempdb..#alltables', 'U') IS NOT NULL DROP TABLE #alltables;",
"SELECT * INTO #alltables FROM INFORMATION_SCHEMA.TABLES;",
"TRUNCATE TABLE #alltables;",
"EXEC sp_MSforeachdb 'USE [?];INSERT INTO #alltables SELECT * from INFORMATION_SCHEMA.TABLES';",
"SELECT * FROM #alltables WHERE TABLE_NAME LIKE '%$0%';",
"GO"
]
}
}

我知道这是一个非常古老的线程,但是当我必须为几个托管不同版本 Sql Server 的不同服务器整合一些系统文档时,它非常有帮助。我最终创建了4个存储过程,我张贴在这里,为了社区的利益。我们使用动态 NAV 使两个存储过程中的名字与 NAV 的名字分离出了导航公司的表名。好好享受。

1 of 4 - ListServerDatabases

USE [YourDatabase]
GO


/****** Object:  StoredProcedure [pssi].[ListServerDatabases]    Script Date: 10/3/2017 8:56:45 AM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO


ALTER PROC [dbo].[ListServerDatabases]
(
@SearchDatabases varchar(max) = NULL,
@ExcludeSystemDatabases bit = 1,
@Sql varchar(max) OUTPUT
)
AS BEGIN


/**************************************************************************************************************************************
* Lists all of the databases for a given server.
*   Parameters
*       SearchDatabases - Comma delimited list of database names for which to search - converted into series of Like statements
*                         Defaults to null
*       ExcludeSystemDatabases - 1 to exclude system databases, otherwise 0
*                                Defaults to 1
*       Sql - Output - the stored proc generated sql
*
*   Adapted from answer by
*   From: How do I list all tables in all databases in SQL Server in a single result set?
*   Link: https://stackoverflow.com/questions/2875768/how-do-i-list-all-tables-in-all-databases-in-sql-server-in-a-single-result-set
*
**************************************************************************************************************************************/


SET NOCOUNT ON


DECLARE @l_CompoundLikeStatement varchar(max) = ''
DECLARE @l_DatabaseName sysname


DECLARE @l_Index int


DECLARE @lUseAndText bit = 0


DECLARE @l_AllDatabases table (ServerName sysname, DbName sysname)


SET @Sql =
'select @@ServerName as ''ServerName'', ''?'' as ''DbName'''


IF @SearchDatabases IS NOT NULL BEGIN
SET @l_CompoundLikeStatement = char(13) + 'where (' + char(13)
WHILE LEN(LTRIM(RTRIM(@SearchDatabases))) > 0 BEGIN
SET @l_Index = CHARINDEX(',', @SearchDatabases)
IF @l_Index = 0 BEGIN
SET @l_DatabaseName = LTRIM(RTRIM(@SearchDatabases))
END ELSE BEGIN
SET @l_DatabaseName = LTRIM(RTRIM(LEFT(@SearchDatabases, @l_Index - 1)))
END


SET @SearchDatabases = LTRIM(RTRIM(REPLACE(LTRIM(RTRIM(REPLACE(@SearchDatabases, @l_DatabaseName, ''))), ',', '')))
SET @l_CompoundLikeStatement = @l_CompoundLikeStatement + char(13) + ' ''?'' like ''' + @l_DatabaseName + '%'' COLLATE Latin1_General_CI_AS or '
END


-- Trim trailing Or and add closing right parenthesis )
SET @l_CompoundLikeStatement = LTRIM(RTRIM(@l_CompoundLikeStatement))
SET @l_CompoundLikeStatement = LEFT(@l_CompoundLikeStatement, LEN(@l_CompoundLikeStatement) - 2) + ' )'


SET @Sql = @Sql + char(13) +
@l_CompoundLikeStatement


SET @lUseAndText = 1
END


IF @ExcludeSystemDatabases = 1 BEGIN
SET @Sql = @Sql + char(13)
SET @Sql = @Sql + case when @lUseAndText = 1 THEN '  and ' ELSE 'where ' END +
'''?'' not in (''master'' COLLATE Latin1_General_CI_AS, ''model'' COLLATE Latin1_General_CI_AS, ''msdb'' COLLATE Latin1_General_CI_AS, ''tempdb'' COLLATE Latin1_General_CI_AS)'
END


/*  PRINT @Sql  */


INSERT INTO @l_AllDatabases
EXEC sp_msforeachdb @Sql


SELECT * FROM @l_AllDatabases ORDER BY DbName
END

我知道这是一个非常古老的线程,但是当我必须为几个托管不同版本 Sql Server 的不同服务器整合一些系统文档时,它非常有帮助。我最终创建了4个存储过程,我张贴在这里,为了社区的利益。我们使用动态 NAV 使两个存储过程中的名字与 NAV 的名字分离出了导航公司的表名。好好享受。

2-ListServerDatabaseTables

USE [YourDatabase]
GO


SET QUOTED_IDENTIFIER ON
GO


ALTER PROC [dbo].[ListServerDatabaseTables]
(
@SearchDatabases varchar(max) = NULL,
@SearchSchema sysname = NULL,
@SearchTables varchar(max) = NULL,
@ExcludeSystemDatabases bit = 1,
@Sql varchar(max) OUTPUT
)
AS BEGIN


/**************************************************************************************************************************************
* Lists all of the database tables for a given server.
*   Parameters
*       SearchDatabases - Comma delimited list of database names for which to search - converted into series of Like statements
*                         Defaults to null
*       SearchSchema - Schema name for which to search
*                      Defaults to null
*       SearchTables - Comma delimited list of table names for which to search - converted into series of Like statements
*                      Defaults to null
*       ExcludeSystemDatabases - 1 to exclude system databases, otherwise 0
*                          Defaults to 1
*       Sql - Output - the stored proc generated sql
*
*   Adapted from answer by KM answered May 21 '10 at 13:33
*   From: How do I list all tables in all databases in SQL Server in a single result set?
*   Link: https://stackoverflow.com/questions/2875768/how-do-i-list-all-tables-in-all-databases-in-sql-server-in-a-single-result-set
*
**************************************************************************************************************************************/


SET NOCOUNT ON


DECLARE @l_CompoundLikeStatement varchar(max) = ''
DECLARE @l_TableName sysname
DECLARE @l_DatabaseName sysname


DECLARE @l_Index int


DECLARE @l_UseAndText bit = 0


DECLARE @AllTables table (ServerName sysname, DbName sysname, SchemaName sysname, TableName sysname)


SET @Sql =
'select @@ServerName as ''ServerName'', ''?'' as ''DbName'', s.name as ''SchemaName'', t.name as ''TableName'' ' + char(13) +
'from [?].sys.tables t inner join ' + char(13) +
'     sys.schemas s on t.schema_id = s.schema_id '


-- Comma delimited list of database names for which to search
IF @SearchDatabases IS NOT NULL BEGIN
SET @l_CompoundLikeStatement = char(13) + 'where (' + char(13)
WHILE LEN(LTRIM(RTRIM(@SearchDatabases))) > 0 BEGIN
SET @l_Index = CHARINDEX(',', @SearchDatabases)
IF @l_Index = 0 BEGIN
SET @l_DatabaseName = LTRIM(RTRIM(@SearchDatabases))
END ELSE BEGIN
SET @l_DatabaseName = LTRIM(RTRIM(LEFT(@SearchDatabases, @l_Index - 1)))
END


SET @SearchDatabases = LTRIM(RTRIM(REPLACE(LTRIM(RTRIM(REPLACE(@SearchDatabases, @l_DatabaseName, ''))), ',', '')))
SET @l_CompoundLikeStatement = @l_CompoundLikeStatement + char(13) + ' ''?'' like ''' + @l_DatabaseName + '%'' COLLATE Latin1_General_CI_AS or '
END


-- Trim trailing Or and add closing right parenthesis )
SET @l_CompoundLikeStatement = LTRIM(RTRIM(@l_CompoundLikeStatement))
SET @l_CompoundLikeStatement = LEFT(@l_CompoundLikeStatement, LEN(@l_CompoundLikeStatement) - 2) + ')'


SET @Sql = @Sql + char(13) +
@l_CompoundLikeStatement


SET @l_UseAndText = 1
END


-- Search schema
IF @SearchSchema IS NOT NULL BEGIN
SET @Sql = @Sql + char(13)
SET @Sql = @Sql + CASE WHEN @l_UseAndText = 1 THEN '  and ' ELSE 'where ' END +
's.name LIKE ''' + @SearchSchema + ''' COLLATE Latin1_General_CI_AS'
SET @l_UseAndText = 1
END


-- Comma delimited list of table names for which to search
IF @SearchTables IS NOT NULL BEGIN
SET @l_CompoundLikeStatement = char(13) + CASE WHEN @l_UseAndText = 1 THEN '  and (' ELSE 'where (' END + char(13)
WHILE LEN(LTRIM(RTRIM(@SearchTables))) > 0 BEGIN
SET @l_Index = CHARINDEX(',', @SearchTables)
IF @l_Index = 0 BEGIN
SET @l_TableName = LTRIM(RTRIM(@SearchTables))
END ELSE BEGIN
SET @l_TableName = LTRIM(RTRIM(LEFT(@SearchTables, @l_Index - 1)))
END


SET @SearchTables = LTRIM(RTRIM(REPLACE(LTRIM(RTRIM(REPLACE(@SearchTables, @l_TableName, ''))), ',', '')))
SET @l_CompoundLikeStatement = @l_CompoundLikeStatement + char(13) + ' t.name like ''$' + @l_TableName + ''' COLLATE Latin1_General_CI_AS or '
END


-- Trim trailing Or and add closing right parenthesis )
SET @l_CompoundLikeStatement = LTRIM(RTRIM(@l_CompoundLikeStatement))
SET @l_CompoundLikeStatement = LEFT(@l_CompoundLikeStatement, LEN(@l_CompoundLikeStatement) - 2) + ' )'


SET @Sql = @Sql + char(13) +
@l_CompoundLikeStatement


SET @l_UseAndText = 1
END


IF @ExcludeSystemDatabases = 1 BEGIN
SET @Sql = @Sql + char(13)
SET @Sql = @Sql + case when @l_UseAndText = 1 THEN '  and ' ELSE 'where ' END +
'''?'' not in (''master'' COLLATE Latin1_General_CI_AS, ''model'' COLLATE Latin1_General_CI_AS, ''msdb'' COLLATE Latin1_General_CI_AS, ''tempdb'' COLLATE Latin1_General_CI_AS)'
END


/*  PRINT @Sql  */


INSERT INTO @AllTables
EXEC sp_msforeachdb @Sql


SELECT * FROM @AllTables ORDER BY DbName COLLATE Latin1_General_CI_AS, SchemaName COLLATE Latin1_General_CI_AS, TableName COLLATE Latin1_General_CI_AS
END

我知道这是一个非常古老的线程,但是当我必须为几个托管不同版本 Sql Server 的不同服务器整合一些系统文档时,它非常有帮助。我最终创建了4个存储过程,我张贴在这里,为了社区的利益。我们使用动态 NAV 使两个存储过程中的名字与 NAV 的名字分离出了导航公司的表名。好好享受。

3-ListServerDatabaseNavCompanies-for Dynamics NAV

USE [YourDatabase]
GO


SET QUOTED_IDENTIFIER ON
GO


ALTER PROC [dbo].[ListServerDatabaseNavCompanies]
(
@SearchDatabases varchar(max) = NULL,
@SearchSchema sysname = NULL,
@SearchCompanies varchar(max) = NULL,
@OrderByDatabaseNameFirst bit = 1,
@ExcludeSystemDatabases bit = 1,
@Sql varchar(max) OUTPUT
)
AS BEGIN


/**************************************************************************************************************************************
* Lists all of the database companies for a given server.
*   Parameters
*       SearchDatabases - Comma delimited list of database names for which to search - converted into series of Like statements
*                         Defaults to null
*       SearchSchema - Schema name for which to search
*                      Defaults to null
*       SearchCompanies - Comma delimited list of company names for which to search - converted into series of Like statements
*                         Defaults to null
*       OrderByDatabaseNameFirst - 1 to sort by Database name and then Company Name, otherwise 0 to sort by Company name first
*                                  Defaults to 1
*       ExcludeSystemDatabases - 1 to exclude system databases, otherwise 0
*                          Defaults to 1
*       Sql - Output - the stored proc generated sql
*
*   Adapted from answer by KM answered May 21 '10 at 13:33
*   From: How do I list all tables in all databases in SQL Server in a single result set?
*   Link: https://stackoverflow.com/questions/2875768/how-do-i-list-all-tables-in-all-databases-in-sql-server-in-a-single-result-set
*
**************************************************************************************************************************************/


SET NOCOUNT ON


DECLARE @l_CompoundLikeStatement varchar(max) = ''
DECLARE @l_CompanyName sysname
DECLARE @l_DatabaseName sysname


DECLARE @l_Index int


DECLARE @l_UseAndText bit = 0


DECLARE @l_Companies table (ServerName sysname, DbName sysname, SchemaName sysname, CompanyName sysname)


SET @Sql =
'select distinct @@ServerName as ''ServerName'', ''?'' as ''DbName'', s.name as ''SchemaName'', ' + char(13) +
'case when charindex(''$'', t.name) = 0 then '''' else left(t.name, charindex(''$'', t.name) - 1) end as ''CompanyName''' + char(13) +
'from [?].sys.tables t inner join ' + char(13) +
'     sys.schemas s on t.schema_id = s.schema_id '


-- Comma delimited list of database names for which to search
IF @SearchDatabases IS NOT NULL BEGIN
SET @l_CompoundLikeStatement = char(13) + 'where (' + char(13)
WHILE LEN(LTRIM(RTRIM(@SearchDatabases))) > 0 BEGIN
SET @l_Index = CHARINDEX(',', @SearchDatabases)
IF @l_Index = 0 BEGIN
SET @l_DatabaseName = LTRIM(RTRIM(@SearchDatabases))
END ELSE BEGIN
SET @l_DatabaseName = LTRIM(RTRIM(LEFT(@SearchDatabases, @l_Index - 1)))
END


SET @SearchDatabases = LTRIM(RTRIM(REPLACE(LTRIM(RTRIM(REPLACE(@SearchDatabases, @l_DatabaseName, ''))), ',', '')))
SET @l_CompoundLikeStatement = @l_CompoundLikeStatement + char(13) + ' ''?'' like ''' + @l_DatabaseName + '%'' COLLATE Latin1_General_CI_AS or '
END


-- Trim trailing Or and add closing right parenthesis )
SET @l_CompoundLikeStatement = LTRIM(RTRIM(@l_CompoundLikeStatement))
SET @l_CompoundLikeStatement = LEFT(@l_CompoundLikeStatement, LEN(@l_CompoundLikeStatement) - 2) + ')'


SET @Sql = @Sql + char(13) +
@l_CompoundLikeStatement


SET @l_UseAndText = 1
END


-- Search schema
IF @SearchSchema IS NOT NULL BEGIN
SET @Sql = @Sql + char(13)
SET @Sql = @Sql + CASE WHEN @l_UseAndText = 1 THEN '  and ' ELSE 'where ' END +
's.name LIKE ''' + @SearchSchema + ''' COLLATE Latin1_General_CI_AS'
SET @l_UseAndText = 1
END


-- Comma delimited list of company names for which to search
IF @SearchCompanies IS NOT NULL BEGIN
SET @l_CompoundLikeStatement = char(13) + CASE WHEN @l_UseAndText = 1 THEN '  and (' ELSE 'where (' END + char(13)
WHILE LEN(LTRIM(RTRIM(@SearchCompanies))) > 0 BEGIN
SET @l_Index = CHARINDEX(',', @SearchCompanies)
IF @l_Index = 0 BEGIN
SET @l_CompanyName = LTRIM(RTRIM(@SearchCompanies))
END ELSE BEGIN
SET @l_CompanyName = LTRIM(RTRIM(LEFT(@SearchCompanies, @l_Index - 1)))
END


SET @SearchCompanies = LTRIM(RTRIM(REPLACE(LTRIM(RTRIM(REPLACE(@SearchCompanies, @l_CompanyName, ''))), ',', '')))
SET @l_CompoundLikeStatement = @l_CompoundLikeStatement + char(13) + ' t.name like ''' + @l_CompanyName + '%'' COLLATE Latin1_General_CI_AS or '
END


-- Trim trailing Or and add closing right parenthesis )
SET @l_CompoundLikeStatement = LTRIM(RTRIM(@l_CompoundLikeStatement))
SET @l_CompoundLikeStatement = LEFT(@l_CompoundLikeStatement, LEN(@l_CompoundLikeStatement) - 2) + ' )'


SET @Sql = @Sql + char(13) +
@l_CompoundLikeStatement


SET @l_UseAndText = 1
END


IF @ExcludeSystemDatabases = 1 BEGIN
SET @Sql = @Sql + char(13)
SET @Sql = @Sql + case when @l_UseAndText = 1 THEN '  and ' ELSE 'where ' END +
'''?'' not in (''master'' COLLATE Latin1_General_CI_AS, ''model'' COLLATE Latin1_General_CI_AS, ''msdb'' COLLATE Latin1_General_CI_AS, ''tempdb'' COLLATE Latin1_General_CI_AS)'
END


/* PRINT @Sql */


INSERT INTO @l_Companies
EXEC sp_msforeachdb @Sql


SELECT CASE WHEN @OrderByDatabaseNameFirst = 1 THEN 'DbName & CompanyName' ELSE 'CompanyName & DbName' END AS 'Sorted by'
SELECT ServerName, DbName COLLATE Latin1_General_CI_AS AS 'DbName', SchemaName COLLATE Latin1_General_CI_AS AS 'SchemaName', CompanyName COLLATE Latin1_General_CI_AS AS 'CompanyName'
FROM @l_Companies
ORDER BY SchemaName COLLATE Latin1_General_CI_AS,
CASE WHEN @OrderByDatabaseNameFirst = 1 THEN DbName COLLATE Latin1_General_CI_AS ELSE CompanyName COLLATE Latin1_General_CI_AS END,
CASE WHEN @OrderByDatabaseNameFirst = 1 THEN CompanyName COLLATE Latin1_General_CI_AS ELSE DbName COLLATE Latin1_General_CI_AS END
END

我知道这是一个非常古老的线程,但是当我必须为几个托管不同版本 Sql Server 的不同服务器整合一些系统文档时,它非常有帮助。我最终创建了4个存储过程,我张贴在这里,为了社区的利益。我们使用动态 NAV 使两个存储过程中的名字与 NAV 的名字分离出了导航公司的表名。好好享受。

4-ListServerDatabaseNavTables-for Dynamics NAV

USE [YourDatabase]
GO


SET QUOTED_IDENTIFIER ON
GO


ALTER proc [dbo].[ListServerDatabaseNavTables]
(
@SearchDatabases varchar(max) = NULL,
@SearchSchema sysname = NULL,
@SearchCompanies varchar(max) = NULL,
@SearchTables varchar(max) = NULL,
@ExcludeSystemDatabases bit = 1,
@Sql varchar(max) OUTPUT
)
AS BEGIN


/**************************************************************************************************************************************
* Lists all of the database tables for a given server.
*   Parameters
*       SearchDatabases - Comma delimited list of database names for which to search - converted into series of Like statements
*                         Defaults to null
*       SearchSchema - Schema name for which to search
*                      Defaults to null
*       SearchCompanies - Comma delimited list of company names for which to search - converted into series of Like statements
*                         Defaults to null
*       SearchTables - Comma delimited list of table names for which to search - converted into series of Like statements
*                      Defaults to null
*       ExcludeSystemDatabases - 1 to exclude system databases, otherwise 0
*                          Defaults to 1
*       Sql - Output - the stored proc generated sql
*
*   Adapted from answer by KM answered May 21 '10 at 13:33
*   From: How do I list all tables in all databases in SQL Server in a single result set?
*   Link: https://stackoverflow.com/questions/2875768/how-do-i-list-all-tables-in-all-databases-in-sql-server-in-a-single-result-set
*
**************************************************************************************************************************************/


SET NOCOUNT ON


DECLARE @l_CompoundLikeStatement varchar(max) = ''
DECLARE @l_TableName sysname
DECLARE @l_CompanyName sysname
DECLARE @l_DatabaseName sysname


DECLARE @l_Index int


DECLARE @l_UseAndText bit = 0


DECLARE @AllTables table (ServerName sysname, DbName sysname, SchemaName sysname, CompanyName sysname, TableName sysname, NavTableName sysname)


SET @Sql =
'select @@ServerName as ''ServerName'', ''?'' as ''DbName'', s.name as ''SchemaName'', ' + char(13) +
'       case when charindex(''$'', t.name) = 0 then '''' else left(t.name, charindex(''$'', t.name) - 1) end as ''CompanyName'', ' + char(13) +
'       case when charindex(''$'', t.name) = 0 then t.name else substring(t.name, charindex(''$'', t.name) + 1, 1000) end as ''TableName'', ' + char(13) +
'       t.name as ''NavTableName'' ' + char(13) +
'from [?].sys.tables t inner join ' + char(13) +
'     sys.schemas s on t.schema_id = s.schema_id '


-- Comma delimited list of database names for which to search
IF @SearchDatabases IS NOT NULL BEGIN
SET @l_CompoundLikeStatement = char(13) + 'where (' + char(13)
WHILE LEN(LTRIM(RTRIM(@SearchDatabases))) > 0 BEGIN
SET @l_Index = CHARINDEX(',', @SearchDatabases)
IF @l_Index = 0 BEGIN
SET @l_DatabaseName = LTRIM(RTRIM(@SearchDatabases))
END ELSE BEGIN
SET @l_DatabaseName = LTRIM(RTRIM(LEFT(@SearchDatabases, @l_Index - 1)))
END


SET @SearchDatabases = LTRIM(RTRIM(REPLACE(LTRIM(RTRIM(REPLACE(@SearchDatabases, @l_DatabaseName, ''))), ',', '')))
SET @l_CompoundLikeStatement = @l_CompoundLikeStatement + char(13) + ' ''?'' like ''' + @l_DatabaseName + '%'' COLLATE Latin1_General_CI_AS or '
END


-- Trim trailing Or and add closing right parenthesis )
SET @l_CompoundLikeStatement = LTRIM(RTRIM(@l_CompoundLikeStatement))
SET @l_CompoundLikeStatement = LEFT(@l_CompoundLikeStatement, LEN(@l_CompoundLikeStatement) - 2) + ')'


SET @Sql = @Sql + char(13) +
@l_CompoundLikeStatement


SET @l_UseAndText = 1
END


-- Search schema
IF @SearchSchema IS NOT NULL BEGIN
SET @Sql = @Sql + char(13)
SET @Sql = @Sql + CASE WHEN @l_UseAndText = 1 THEN '  and ' ELSE 'where ' END +
's.name LIKE ''' + @SearchSchema + ''' COLLATE Latin1_General_CI_AS'
SET @l_UseAndText = 1
END


-- Comma delimited list of company names for which to search
IF @SearchCompanies IS NOT NULL BEGIN
SET @l_CompoundLikeStatement = char(13) + CASE WHEN @l_UseAndText = 1 THEN '  and (' ELSE 'where (' END + char(13)
WHILE LEN(LTRIM(RTRIM(@SearchCompanies))) > 0 BEGIN
SET @l_Index = CHARINDEX(',', @SearchCompanies)
IF @l_Index = 0 BEGIN
SET @l_CompanyName = LTRIM(RTRIM(@SearchCompanies))
END ELSE BEGIN
SET @l_CompanyName = LTRIM(RTRIM(LEFT(@SearchCompanies, @l_Index - 1)))
END


SET @SearchCompanies = LTRIM(RTRIM(REPLACE(LTRIM(RTRIM(REPLACE(@SearchCompanies, @l_CompanyName, ''))), ',', '')))
SET @l_CompoundLikeStatement = @l_CompoundLikeStatement + char(13) + ' t.name like ''' + @l_CompanyName + '%'' COLLATE Latin1_General_CI_AS or '
END


-- Trim trailing Or and add closing right parenthesis )
SET @l_CompoundLikeStatement = LTRIM(RTRIM(@l_CompoundLikeStatement))
SET @l_CompoundLikeStatement = LEFT(@l_CompoundLikeStatement, LEN(@l_CompoundLikeStatement) - 2) + ' )'


SET @Sql = @Sql + char(13) +
@l_CompoundLikeStatement


SET @l_UseAndText = 1
END


-- Comma delimited list of table names for which to search
IF @SearchTables IS NOT NULL BEGIN
SET @l_CompoundLikeStatement = char(13) + CASE WHEN @l_UseAndText = 1 THEN '  and (' ELSE 'where (' END + char(13)
WHILE LEN(LTRIM(RTRIM(@SearchTables))) > 0 BEGIN
SET @l_Index = CHARINDEX(',', @SearchTables)
IF @l_Index = 0 BEGIN
SET @l_TableName = LTRIM(RTRIM(@SearchTables))
END ELSE BEGIN
SET @l_TableName = LTRIM(RTRIM(LEFT(@SearchTables, @l_Index - 1)))
END


SET @SearchTables = LTRIM(RTRIM(REPLACE(LTRIM(RTRIM(REPLACE(@SearchTables, @l_TableName, ''))), ',', '')))
SET @l_CompoundLikeStatement = @l_CompoundLikeStatement + char(13) + ' t.name like ''$' + @l_TableName + ''' COLLATE Latin1_General_CI_AS or '
END


-- Trim trailing Or and add closing right parenthesis )
SET @l_CompoundLikeStatement = LTRIM(RTRIM(@l_CompoundLikeStatement))
SET @l_CompoundLikeStatement = LEFT(@l_CompoundLikeStatement, LEN(@l_CompoundLikeStatement) - 2) + ' )'


SET @Sql = @Sql + char(13) +
@l_CompoundLikeStatement


SET @l_UseAndText = 1
END


IF @ExcludeSystemDatabases = 1 BEGIN
SET @Sql = @Sql + char(13)
SET @Sql = @Sql + case when @l_UseAndText = 1 THEN '  and ' ELSE 'where ' END +
'''?'' not in (''master'' COLLATE Latin1_General_CI_AS, ''model'' COLLATE Latin1_General_CI_AS, ''msdb'' COLLATE Latin1_General_CI_AS, ''tempdb'' COLLATE Latin1_General_CI_AS)'
END


/*  PRINT @Sql  */


INSERT INTO @AllTables
EXEC sp_msforeachdb @Sql


SELECT * FROM @AllTables ORDER BY DbName COLLATE Latin1_General_CI_AS, CompanyName COLLATE Latin1_General_CI_AS, TableName COLLATE Latin1_General_CI_AS
END

下面的教程提供了一个 T-SQL 脚本,该脚本将为位于 SQL Server 实例中的每个数据库中的每个表返回以下字段:

  1. 服务器名称
  2. DatabaseName
  3. SchemaName
  4. 表名
  5. 列名
  6. 键盘输入法

Https://tidbytez.com/2015/06/01/map-the-table-structure-of-a-sql-server-database/

/*
SCRIPT UPDATED
20180316
*/


USE [master]
GO


/*DROP TEMP TABLES IF THEY EXIST*/
IF OBJECT_ID('tempdb..#DatabaseList') IS NOT NULL
DROP TABLE #DatabaseList;


IF OBJECT_ID('tempdb..#TableStructure') IS NOT NULL
DROP TABLE #TableStructure;


IF OBJECT_ID('tempdb..#ErrorTable') IS NOT NULL
DROP TABLE #ErrorTable;


IF OBJECT_ID('tempdb..#MappedServer') IS NOT NULL
DROP TABLE #MappedServer;


DECLARE @ServerName AS SYSNAME


SET @ServerName = @@SERVERNAME


CREATE TABLE #DatabaseList (
Id INT NOT NULL IDENTITY(1, 1) PRIMARY KEY
,ServerName SYSNAME
,DbName SYSNAME
);


CREATE TABLE [#TableStructure] (
[DbName] SYSNAME
,[SchemaName] SYSNAME
,[TableName] SYSNAME
,[ColumnName] SYSNAME
,[KeyType] CHAR(7)
) ON [PRIMARY];


/*THE ERROR TABLE WILL STORE THE DYNAMIC SQL THAT DID NOT WORK*/
CREATE TABLE [#ErrorTable] ([SqlCommand] VARCHAR(MAX)) ON [PRIMARY];


/*
A LIST OF DISTINCT DATABASE NAMES IS CREATED
THESE TWO COLUMNS ARE STORED IN THE #DatabaseList TEMP TABLE
THIS TABLE IS USED IN A FOR LOOP TO GET EACH DATABASE NAME
*/
INSERT INTO #DatabaseList (
ServerName
,DbName
)
SELECT @ServerName
,NAME AS DbName
FROM master.dbo.sysdatabases WITH (NOLOCK)
WHERE NAME <> 'tempdb'
ORDER BY NAME ASC


/*VARIABLES ARE DECLARED FOR USE IN THE FOLLOWING FOR LOOP*/
DECLARE @sqlCommand AS VARCHAR(MAX)
DECLARE @DbName AS SYSNAME
DECLARE @i AS INT
DECLARE @z AS INT


SET @i = 1
SET @z = (
SELECT COUNT(*) + 1
FROM #DatabaseList
)


/*WHILE 1 IS LESS THAN THE NUMBER OF DATABASE NAMES IN #DatabaseList*/
WHILE @i < @z
BEGIN
/*GET NEW DATABASE NAME*/
SET @DbName = (
SELECT [DbName]
FROM #DatabaseList
WHERE Id = @i
)
/*CREATE DYNAMIC SQL TO GET EACH TABLE NAME AND COLUMN NAME FROM EACH DATABASE*/
SET @sqlCommand = 'USE [' + @DbName + '];' + '


INSERT INTO [#TableStructure]
SELECT DISTINCT' + '''' + @DbName + '''' + ' AS DbName
,SCHEMA_NAME(SCHEMA_ID) AS SchemaName
,T.NAME AS TableName
,C.NAME AS ColumnName
,CASE
WHEN OBJECTPROPERTY(OBJECT_ID(iskcu.CONSTRAINT_NAME), ''IsPrimaryKey'') = 1
THEN ''Primary''
WHEN OBJECTPROPERTY(OBJECT_ID(iskcu.CONSTRAINT_NAME), ''IsForeignKey'') = 1
THEN ''Foreign''
ELSE NULL
END AS ''KeyType''
FROM SYS.TABLES AS t WITH (NOLOCK)
INNER JOIN SYS.COLUMNS C ON T.OBJECT_ID = C.OBJECT_ID
LEFT JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE AS iskcu WITH (NOLOCK)
ON SCHEMA_NAME(SCHEMA_ID) = iskcu.TABLE_SCHEMA
AND T.NAME = iskcu.TABLE_NAME
AND C.NAME = iskcu.COLUMN_NAME
ORDER BY SchemaName ASC
,TableName ASC
,ColumnName ASC;
';


/*ERROR HANDLING*/
BEGIN TRY
EXEC (@sqlCommand)
END TRY


BEGIN CATCH
INSERT INTO #ErrorTable
SELECT (@sqlCommand)
END CATCH


SET @i = @i + 1
END


/*
JOIN THE TEMP TABLES TOGETHER TO CREATE A MAPPED STRUCTURE OF THE SERVER
ADDITIONAL FIELDS ARE ADDED TO MAKE SELECTING TABLES AND FIELDS EASIER
*/
SELECT DISTINCT @@SERVERNAME AS ServerName
,DL.DbName
,TS.SchemaName
,TS.TableName
,TS.ColumnName
,TS.[KeyType]
,',' + QUOTENAME(TS.ColumnName) AS BracketedColumn
,',' + QUOTENAME(TS.TableName) + '.' + QUOTENAME(TS.ColumnName) AS BracketedTableAndColumn
,'SELECT * FROM ' + QUOTENAME(DL.DbName) + '.' + QUOTENAME(TS.SchemaName) + '.' + QUOTENAME(TS.TableName) + '--WHERE --GROUP BY --HAVING --ORDER BY' AS [SelectTable]
,'SELECT ' + QUOTENAME(TS.TableName) + '.' + QUOTENAME(TS.ColumnName) + ' FROM ' + QUOTENAME(DL.DbName) + '.' + QUOTENAME(TS.SchemaName) + '.' + QUOTENAME(TS.TableName) + '--WHERE --GROUP BY --HAVING --ORDER BY' AS [SelectColumn]
INTO #MappedServer
FROM [#DatabaseList] AS DL
INNER JOIN [#TableStructure] AS TS ON DL.DbName = TS.DbName
ORDER BY DL.DbName ASC
,TS.SchemaName ASC
,TS.TableName ASC
,TS.ColumnName ASC


/*
HOUSE KEEPING
*/
IF OBJECT_ID('tempdb..#DatabaseList') IS NOT NULL
DROP TABLE #DatabaseList;


IF OBJECT_ID('tempdb..#TableStructure') IS NOT NULL
DROP TABLE #TableStructure;


SELECT *
FROM #ErrorTable;


IF OBJECT_ID('tempdb..#ErrorTable') IS NOT NULL
DROP TABLE #ErrorTable;


/*
THE DATA RETURNED CAN NOW BE EXPORTED TO EXCEL
USING A FILTERED SEARCH WILL NOW MAKE FINDING FIELDS A VERY EASY PROCESS
*/
SELECT ServerName
,DbName
,SchemaName
,TableName
,ColumnName
,KeyType
,BracketedColumn
,BracketedTableAndColumn
,SelectColumn
,SelectTable
FROM #MappedServer
ORDER BY DbName ASC
,SchemaName ASC
,TableName ASC
,ColumnName ASC;

请为搜索表填写@likeTablename 参数。

现在这个参数设置为% tbltrans% ,用于搜索名称中包含 tbltrans 的所有表。

将@likeTablename 设置为“%”以显示所有表。

declare @AllTableNames nvarchar(max);


select  @AllTableNames=STUFF((select ' SELECT  TABLE_CATALOG collate DATABASE_DEFAULT+''.''+TABLE_SCHEMA collate DATABASE_DEFAULT+''.''+TABLE_NAME collate DATABASE_DEFAULT as tablename FROM '+name+'.INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = ''BASE TABLE'' union '
FROM master.sys.databases
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'');


set @AllTableNames=left(@AllTableNames,len(@AllTableNames)-6)


declare @likeTablename nvarchar(200)='%tbltrans%';
set @AllTableNames=N'select tablename from('+@AllTableNames+N')at where tablename like '''+N'%'+@likeTablename+N'%'+N''''
exec sp_executesql  @AllTableNames

链接到 Bart Gawrych 在 Dataedo 站点上发布的无存储过程方法

I was asking myself, 'Do we really have to use a stored procedure here?' and I found this helpful post. (The state=0 was added to fix issues with offline databases per feedback from users of the linked page.)

declare @sql nvarchar(max);


select @sql =
(select ' UNION ALL
SELECT ' +  + quotename(name,'''') + ' as database_name,
s.name COLLATE DATABASE_DEFAULT
AS schema_name,
t.name COLLATE DATABASE_DEFAULT as table_name
FROM '+ quotename(name) + '.sys.tables t
JOIN '+ quotename(name) + '.sys.schemas s
on s.schema_id = t.schema_id'
from sys.databases
where state=0
order by [name] for xml path(''), type).value('.', 'nvarchar(max)');


set @sql = stuff(@sql, 1, 12, '') + ' order by database_name,
schema_name,
table_name';


execute (@sql);

我使用了 KM 的答案,并且在其中添加了 Columns,因为这是我最常用的用例之一。我还将它插入到一个表中,这样就可以将这些数据用于不同的 DQ 用途。因为花了我几分钟,我想节省别人的时间。这就是:

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


INSERT INTO @AllTables (DbName, SchemaName, TableName, ColumnName)
EXEC sp_msforeachdb @SQL
SET NOCOUNT OFF
SELECT * into ##DBSchTabCol
FROM @AllTables ORDER BY DbName, SchemaName, TableName, ColumnName