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

时间:2010-05-20 16:23:22

标签: sql-server metadata

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

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

上面的存储过程为每个数据库生成一个结果集 ,如果您在像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;

2010.05.24更新 - 新的领跑者!

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

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

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

  

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

查询 成功使用一些过滤条款 - 那些不会触及访问级别之外的数据库的过滤条款。

次要问题:不容易降级到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

16 个答案:

答案 0 :(得分:34)

获取服务器上所有表的简单方法,试试这个:

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

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

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

如果您不在SQL Server 2005或更高版本上,请将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'或'.master.dbo'之类的内容,或甚至包含'.master。%。u'等通配符。< / p>

答案 1 :(得分: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;

答案 2 :(得分:9)

我需要一些东西,我可以使用CMS搜索我的所有服务器,并按服务器,数据库,架构或表搜索。这是我发现的(最初由Michael Sorens在这里发布:How do I list all tables in all databases in SQL Server in a single result set?)。

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

答案 3 :(得分:2)

我在这里发布了一段你可以使用的答案here。大纲是:

  • 创建临时表
  • 调用sp_msForEachDb
  • 针对每个数据库运行的查询将数据存储在临时表
  • 完成后,查询临时表

答案 4 :(得分:1)

我非常喜欢使用INFORMATION_SCHEMA,因为我免费获得了DB名称。那并且 - 从@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

答案 5 :(得分:1)

我认为使用SELECT * FROM INFORMATION_SCHEMA.TABLES

的每个数据库的常见方法是sp_MSforeachdb

我在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"
        ]
    }
}

答案 6 :(得分:1)

我意识到这是一个非常老的线程,但是当我必须为托管不同版本的Sql Server的几个不同服务器组装一些系统文档时,它非常有用。我最终创建了4个存储过程,我在这里发布这些过程是为了社区的利益。我们使用Dynamics NAV,因此名称中带有NAV的两个存储过程将Nav公司从表名中分离出来。享受...

4 of 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

答案 7 :(得分:0)

我很确定你必须遍历数据库列表然后列出每个表。你应该能够将它们结合在一起。

答案 8 :(得分:0)

您需要做的就是运行sp_tables存储过程。 http://msdn.microsoft.com/en-us/library/aa260318(SQL.80).aspx

答案 9 :(得分:0)

这非常方便,但我想要一种方法来显示所有用户对象,而不仅仅是表,所以我改编它使用sys.objects而不是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

答案 10 :(得分:0)

我意识到这是一个非常老的线程,但是当我必须为托管不同版本的Sql Server的几个不同服务器组装一些系统文档时,它非常有用。我最终创建了4个存储过程,我在这里发布这些过程是为了社区的利益。我们使用Dynamics NAV,因此名称中带有NAV的两个存储过程将Nav公司从表名中分离出来。享受...

4 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

答案 11 :(得分:0)

我意识到这是一个非常老的线程,但是当我必须为托管不同版本的Sql Server的几个不同服务器组装一些系统文档时,它非常有用。我最终创建了4个存储过程,我在这里发布这些过程是为了社区的利益。我们使用Dynamics NAV,因此名称中带有NAV的两个存储过程将Nav公司从表名中分离出来。享受...

2 of 4 - 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

答案 12 :(得分:0)

我意识到这是一个非常老的线程,但是当我必须为托管不同版本的Sql Server的几个不同服务器组装一些系统文档时,它非常有用。我最终创建了4个存储过程,我在这里发布这些过程是为了社区的利益。我们使用Dynamics NAV,因此名称中带有NAV的两个存储过程将Nav公司从表名中分离出来。享受...

3 of 4 - 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

答案 13 :(得分:0)

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

现在此参数设置为%tbltrans%,以搜索所有表名称中包含tbltrans的

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

app.yaml

答案 14 :(得分:0)

Link to a stored-procedure-less approach that Bart Gawrych posted on Dataedo site

我问自己:'我们真的必须在这里使用存储过程吗?'我发现这篇有用的文章。 (已添加状态= 0,以根据链接页面的用户的反馈来解决离线数据库的问题。)

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);

答案 15 :(得分:-1)

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

  1. ServerName
  2. DatabaseName
  3. 架构名称
  4. TableName
  5. ColumnName
  6. 关键字类型
  7. 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;