我正在寻找 T-SQL 代码列出所有数据库中的所有表在 SQL 服务器(至少在 SS2005和 SS2008; 将是不错的,也适用于 SS2000)。然而,问题是我想要一个 单个结果集。这就排除了 皮纳尔 · 戴夫的另一个绝佳答案:
sp_msforeachdb 'select "?" AS db, * from [?].sys.tables'
上面存储的 proc 生成一个结果集 每个数据库 ,如果您处于能够显示多个结果集的像 SSMS 这样的 IDE 中,这样做是可以的。然而,我想要一个单一的结果集,因为我想要一个本质上是一个“查找”工具的查询: 如果我添加一个像 WHERE tablename like '%accounts'
这样的子句,那么它会告诉我在哪里可以找到我的 BillAccount、 ClientAccount 和 VendorAccount 表,而不管它们位于哪个数据库中。
到目前为止,莱姆斯的回答看起来最有趣。而不是张贴这个作为一个答案和奖励它给我自己,我在这里张贴它的一个版本,我已经修改,以包括数据库名称和一个示例过滤器子句。看起来莱姆斯将得到答案的荣誉,虽然,在这一点上!
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;
反馈和回答非常棒。持续的协作参与导致了 新的领跑者: KM 的答案从5月21日!
Here are the issues I uncovered with Remus' solution:
主要问题: 用户拥有不同的权限,这会导致基于数据(即过滤值)的查询成功。使用 强过滤在我的生产数据库上运行(即省略 WHERE
子句) ,我在几个没有访问权限的 DBs 上收到了这个错误:
服务器主体“ msoren”无法访问数据库 当前安全上下文下的“ ETLprocDB”。
查询 意志坚强使用一些过滤子句取得了成功——这些子句没有触及访问级别之外的 DBs。
次要问题: 不容易降级到 SQL Server 2000支持(是的,我们仍然有一些人在使用它...) ,因为它在为每个数据库累积条目时构建一个单独的字符串。通过我的系统,我在大约40个数据库中超过了8000个字符的标准。
Minor issue: Duplicate code--the loop setup essentially duplicates the loop body. I understand the rationale but it is just a pet peeve of mine...
知识管理的答案并没有受到这些问题的影响。存储过程 sp_msforeachdb
考虑到用户的权限,因此可以避免权限问题。我还没有尝试与 SS2000的代码,但知识管理表明的调整,应该做到这一点。
接下来我将根据个人喜好对 KM 的回答进行修改,具体如下:
Here is my modification to KM's code (with a sample filter applied just to the table name):
SET NOCOUNT ON
DECLARE @AllTables table (DbName sysname,SchemaName sysname, TableName sysname)
DECLARE
@SearchDb nvarchar(200)
,@SearchSchema nvarchar(200)
,@SearchTable nvarchar(200)
,@SQL nvarchar(4000)
SET @SearchDb='%'
SET @SearchSchema='%'
SET @SearchTable='%Account%'
SET @SQL='select ''?'' as DbName, s.name as SchemaName, t.name as TableName from [?].sys.tables t inner join [?].sys.schemas s on t.schema_id=s.schema_id WHERE ''?'' LIKE '''+@SearchDb+''' AND s.name LIKE '''+@SearchSchema+''' AND t.name LIKE '''+@SearchTable+''''
INSERT INTO @AllTables (DbName, SchemaName, TableName)
EXEC sp_msforeachdb @SQL
SET NOCOUNT OFF
SELECT * FROM @AllTables ORDER BY DbName, SchemaName, TableName