【问题标题】:How do I list all tables in all databases in SQL Server in a single result set?如何在单个结果集中列出 SQL Server 中所有数据库中的所有表?
【发布时间】:2011-02-21 23:27:05
【问题描述】:

我正在寻找 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 的解决方案中发现的问题:

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

服务器主体“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

【问题讨论】:

  • 足智多谋+1,希望它能鼓励其他人尽职尽责。
  • 查看我的答案,它有一种非常简单但灵活的方式来搜索服务器+数据库+模式+表名的任何部分
  • KM:感谢发帖;我更新了我的问题,解释了为什么我现在更喜欢你的解决方案。
  • [?].sys.tables t inner join sys.schemas 将只返回模式 dbo 中的表,您应该 [?].sys.tables t inner join [?].sys.schemas 以便针对同一数据库中的模式运行表。
  • 我已将最终答案更新为使用 [?].sys.schemas。我自己几乎错过了。我通常不会更新其他人的答案,但这似乎是一个非常明显的疏忽,我不希望其他人在没有意识到他们只得到部分结果的情况下使用它(b/c 在我的情况下,数据库之间有很多重复的 ID所以它实际上确实从每个数据库返回了很多表)。

标签: sql-server metadata


【解决方案1】:

我使用了 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

【讨论】:

    【解决方案2】:

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

    我在问自己,“我们真的必须在这里使用存储过程吗?”我发现这个有用的帖子。 (添加 state=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);
    

    【讨论】:

      【解决方案3】:

      请填写搜索表的@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
      

      【讨论】:

        【解决方案4】:

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

        1. 服务器名称
        2. 数据库名称
        3. 架构名称
        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;
        

        【讨论】:

          【解决方案5】:

          我需要一些可以使用 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
          

          【讨论】:

          • 我认为你应该在 JOIN 中使用 [?].sys.schemas 而不是 sys.schemas
          【解决方案6】:

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

          4 of 4 - ListServerDatabaseNavTables - 用于 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】:

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

            3 of 4 - ListServerDatabaseNavCompanies - 用于 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
            

            【讨论】:

              【解决方案8】:

              我意识到这是一个非常古老的线程,但是当我必须为托管不同版本的 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
              

              【讨论】:

                【解决方案9】:

                我意识到这是一个非常古老的线程,但是当我必须为托管不同版本的 Sql Server 的多个不同服务器整理一些系统文档时,它非常有帮助。我最终创建了 4 个存储过程,我将它们发布在这里以造福社区。我们使用 Dynamics NAV,因此名称中带有 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
                

                【讨论】:

                  【解决方案10】:

                  我认为常见的方法是为每个数据库使用SELECT * FROM INFORMATION_SCHEMA.TABLESsp_MSforeachdb

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

                  查询

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

                  【讨论】:

                    【解决方案11】:

                    我非常喜欢为此使用 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
                    

                    【讨论】:

                      【解决方案12】:

                      这真的很方便,但我想要一种方法来显示所有用户对象,而不仅仅是表,所以我对其进行了调整以使用 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
                      

                      【讨论】:

                        【解决方案13】:

                        我不久前发布了一个答案here,您可以在此处使用。大纲是:

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

                        【讨论】:

                        • 听起来提问者更喜欢类似视图的界面,而不是存储过程,这样他就可以使用 SQL 来过滤结果。据我所知,您的建议使这变得更加困难。
                        • @WCWedin:然后使用普通表,而不是临时表。我看到这种方法的唯一问题是,如果数据模型经常变化(无论如何都非常糟糕),它可能会不同步。
                        • @OMG Ponies:是的,问题比比皆是。这可能是最好的解决方案,但它并不理想。我不是想成为批评家,但是……好吧,我想我是。不过,我的意思是。
                        • 我的策略是获取数据,但尚不完全清楚用户需要以何种形式获取数据。另请注意,在存储过程中,您可以嵌入检查 SQL 版本号的代码 ( @@Version),并在此基础上运行必要的查询——sys.tables、sysobjects、INFORMATION_SCHEMA 等等。
                        【解决方案14】:

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

                        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”等通配符等。

                        【讨论】:

                        • 我开始尝试在 SQL Server 2000 上进行此操作,发现它适用于您指出的简单更改--sys.tables 和 sys.schemas 不可用直到 SS2005。
                        • 替换这一行:SET @SQL='select @@SERVERNAME+''.''+''?''+''.''+s.name+''.''+t.name from [?]..sysobjects t inner join sysusers s on t.uid=s.uid WHERE @@SERVERNAME+''.''+''?''+''.''+s.name+''.''+t.name LIKE ''%'+ISNULL(@SEARCH,'')+'%'''
                        【解决方案15】:
                        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;
                        

                        【讨论】:

                        • +1 非常聪明!也可以将数据库名称添加到选定的属性列表中吗?
                        • 很酷,但 OP 还想添加 where 子句,因此您可能必须将其纳入动态 SQL
                        • 我已修改此代码以包含数据库名称(如 marc_s 所建议)和过滤器(如 RobS 所建议),但由于 cmets 有限,请参阅我的问题顶部的更新页。 (我选择这样做而不是添加单独的答案,因为我现在倾向于给予 Remus 功劳......)
                        • 我也修改为项目 dbname。需要注意的是联合列表中的第一个数据库名称决定了结果列的长度,如果太短可能会截断后续的数据库名称。我选择强制转换为 sysname(sys.databases.name 的类型),并使用 quotename 函数在来自 sys.databases 的名称周围正确添加单引号。没有添加 where 子句,因为 OP 知道怎么做 :)
                        • 关于长度的好消息...还有一个问题:为什么要明确指定名称的排序规则?
                        【解决方案16】:

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

                        【讨论】:

                        • ... 对于每个数据库。所以至少sp_msForEachDb 'USE [?] EXEC sp_tables',但这仍然是单独的结果。
                        【解决方案17】:

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

                        【讨论】:

                          猜你喜欢
                          • 1970-01-01
                          • 2011-02-13
                          • 2018-02-07
                          • 2020-07-19
                          • 1970-01-01
                          • 1970-01-01
                          • 2017-10-06
                          • 1970-01-01
                          • 1970-01-01
                          相关资源
                          最近更新 更多