1

如果我有一组这样的名称:

('first', 'fname', 'firstname', 'namef', 'namefirst', 'name')

SQL Server 2000 - 2008 中检索包含特定数据库上述集合中列名的不同表名的最佳方法是什么?

我想从显示的表列表中排除系统表和临时表。

SELECT so.name
FROM   sysobjects so
       INNER JOIN syscolumns sc
            ON  so.id = sc.id
WHERE  sc.name IN ('first', 'fname', 'firstname', 'namef', 'namefirst', 'name')

我相信这是这个问题的派生词。

谢谢

4

2 回答 2

4

对于 SQL Server 2005 及更高版本

对于较新版本的 SQL Server 的 FWIW 我更喜欢目录视图INFORMATION_SCHEMA,原因在此博客文章中概述:

反对INFORMATION_SCHEMA意见的案例

另请参阅MSDN上关于TABLES (Transact-SQL)主题的警告:

不要使用 INFORMATION_SCHEMA 视图来确定对象的架构。查找对象架构的唯一可靠方法是查询 sys.objects 目录视图。INFORMATION_SCHEMA 视图可能不完整,因为它们并未针对所有新功能进行更新。

因此,我将使用的查询如下(过滤掉系统对象并在您使用 tempdb 时避免使用 #temp 表):

SELECT t.name, c.name
  FROM sys.tables AS t
  INNER JOIN sys.columns AS c
  ON t.[object_id] = c.[object_id]
  WHERE c.name IN (N'name', N'firstname', etc.)
  AND t.is_ms_shipped = 0
  AND t.name NOT LIKE '#%';

对所有数据库重复此操作:

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

SELECT @sql += N'
  UNION ALL SELECT db = N''' + name + ''', 
    t.name COLLATE Latin1_General_CI_AI, 
    c.name COLLATE Latin1_General_CI_AI
  FROM ' + QUOTENAME(name) + '.sys.tables AS t
  INNER JOIN ' + QUOTENAME(name) + 'sys.columns AS c
  ON t.[object_id] = c.[object_id]
  WHERE c.name IN (N''name'', N''firstname'', etc.)
  AND t.is_ms_shipped = 0
  AND t.name NOT LIKE ''#%'''
FROM sys.databases
-- WHERE ... -- probably don't need system databases at least

SELECT @sql = STUFF(@sql, 1, 18, '') 
  -- you may have to adjust  ^^ 18 based on copy/paste, cr/lf, tabs etc.
  + ' ORDER BY by db, s.name, o.name';

EXEC sp_executesql @sql;

(这些COLLATE子句是为了防止在您拥有具有不同排序规则的数据库的情况下出现错误。)

对于 SQL Server 2000

请注意,上述内容对 SQL Server 2000 没有帮助,但我认为您不应该将能够在每个版本上运行相同的查询作为目标。SQL Server 2000 已有 13 年的历史,几年后不再支持;当然,您可以证明有特殊代码是合理的。在这种情况下,我仍然会选择您所拥有的查询INFORMATION_SCHEMA,只需过滤掉系统对象和临时表(同样,仅与您在 tempdb 中的事件相关):

SELECT [object] = so.name, [column] = sc.name, 
  [type]  = st.name,   [precision] = st.xprec, 
  [scale] = st.xscale, st.length
FROM sysobjects AS so
INNER JOIN syscolumns AS sc
ON  so.id = sc.id
INNER JOIN systypes AS st
ON sc.xtype = st.xtype
WHERE sc.name IN 
  (N'first', N'fname', N'firstname', N'namef', N'namefirst', N'name')
AND so.name NOT LIKE '#%'
AND OBJECTPROPERTY(so.id, 'IsMsShipped') = 0;

您也可以对 SQL Server 2000 中的每个数据库执行此操作,但由于您不能使用NVARCHAR(MAX),您将不得不使用游标、一堆变量或高度不推荐的 sp_msforeachdb

于 2013-01-25T16:28:10.063 回答
3

您可以使用INFORMATION_SCHEMA架构。

SELECT DISTINCT t.TABLE_NAME
  FROM INFORMATION_SCHEMA.TABLES t
  JOIN INFORMATION_SCHEMA.COLUMNS c
  ON t.TABLE_NAME = c.TABLE_NAME
  WHERE c.COLUMN_NAME IN (your list of names)

我不记得这是否包括临时表,但您可以查看其他列TABLES以查看要过滤的内容。

于 2013-01-25T15:56:17.063 回答