5

列出服务器上所有带有模式的表是没有问题的

SELECT SCHEMA_NAME(schema_id), name FROM sys.tables

如何确定表驻留在哪个数据库中?

4

3 回答 3

10

sys.tables 存在于所有数据库中,所以我没有遵循您不知道您所在的数据库的事实。您可以运行 DB_NAME(DB_ID()) 来获取数据库名称

SELECT  DB_NAME(DB_ID()),SCHEMA_NAME(schema_id), name FROM sys.tables

但在这种情况下 DB_NAME(DB_ID()) 将为每一行返回相同的值

为所有数据库执行此操作,您可以执行此操作

EXEC sp_msforeachdb 'use  [?] SELECT  ''?'',SCHEMA_NAME(schema_id), name 
                                  FROM sys.tables'

您当然也可以将其转储到表格中

CREATE TABLE #output (DatabaseName VARCHAR(1000), 
                   SchemaName VARCHAR(1000), 
                  TableName VARCHAR(1000))

INSERT #output
EXEC sp_msforeachdb 'use  [?] SELECT  ''?'',SCHEMA_NAME(schema_id), name 
                                  FROM sys.tables'

SELECT * FROM #output

仅供参考,sp_msforeachdb proc 没有记录,您不应该将它用于生产代码,快速找到一些东西是好的,生产代码滚动您自己的这个 proc 版本

另请参阅 Aaron Bertrand 的帖子:

于 2012-05-31T16:53:29.350 回答
4

我在创建查询时遇到了这个问题,我希望能够在我的服务器上对不同的数据库运行,并在不将其硬编码到查询中的情况下包含另一个数据库的名称。

查询基本上如下所示:

SELECT DB_NAME() db_name
     , SCHEMA_NAME(schema_id) schema_name
     , name table_name
  FROM OtherDB.sys.tables   --The OtherDB is to specify that I am running
                            --this for a different database than the one
                            --I'm logged in to for my current session.

问题是,即使我OtherDB.sys.tables在 from 子句中指定,DB_NAME()总是返回我所在的当前数据库。是的,我可以USE OtherDB在开头放 a,但似乎应该有另一种方式。我浏览了我能找到的每一个 sys 视图,但找不到任何可以链接sys.databasessys.tables.

我最终发现的是 SQL Server 的INFORMATION_SCHEMA.TABLES这个视图包括数据库名称作为第一列(称为TABLE_CATAOLG)。

SELECT TABLE_CATALOG
     , TABLE_SCHEMA
     , TABLE_NAME
     , TABLE_TYPE
  FROM INFORMATION_SCHEMA.TABLES

使用这些视图,您可以轻松比较两个数据库中的表:

SELECT a.TABLE_CATALOG
     , a.TABLE_SCHEMA
     , a.TABLE_NAME
     , a.TABLE_TYPE
     , b.TABLE_CATALOG
     , b.TABLE_SCHEMA
     , b.TABLE_NAME
     , b.TABLE_TYPE
  FROM OneDatabase.INFORMATION_SCHEMA.TABLES a
  FULL OUTER JOIN TwoDatabase.INFORMATION_SCHEMA.TABLES b 
    ON a.TABLE_SCHEMA = b.TABLE_SCHEMA
   AND a.TABLE_NAME = b.TABLE_NAME

如果数据库位于链接的单独服务器上,您应该能够通过使用Full Qualified Table Name的所有四个部分来使用此查询。

于 2014-07-22T19:59:02.870 回答
1

如果您的意图只是包含当前数据库名称,为什么不只是:

SELECT DB_NAME(), SCHEMA_NAME(schema_id), name FROM sys.tables;

如果您的意图是从所有数据库中提取所有名称,我个人更喜欢这样的动态 SQL,而不是sp_msforeachdb

DECLARE @sql NVARCHAR(MAX) = N'';

SELECT @sql += CHAR(13) + CHAR(10) + 'UNION ALL 
    SELECT ''' + name + ''', s.name, t.name
    FROM ' + QUOTENAME(name) + '.sys.tables AS t
    INNER JOIN ' + QUOTENAME(name) + '.sys.schemas AS s
    ON t.schema_id = s.schema_id'
    FROM sys.databases
    WHERE database_id > 4;

SET @sql = STUFF(@sql, 1, 13, '');

PRINT @sql;

-- EXEC sp_executesql @sql;
于 2012-05-31T17:24:36.800 回答