如何从SQL Server 2000-2008中的多个表中选择一组名称中的列名

时间:2013-01-25 15:52:18

标签: sql-server sql-server-2008 sql-server-2005 sql-server-2000

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

('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')

我相信这是question的衍生物。

THX

2 个答案:

答案 0 :(得分:4)

对于SQL Server 2005及更高版本

对于较新版本的SQL Server的FWIW我更喜欢INFORMATION_SCHEMA上的目录视图,原因如下:

The case against INFORMATION_SCHEMA views

另请参阅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),您将不得不使用游标,一堆变量或highly not-recommended sp_msforeachdb

答案 1 :(得分: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中的其他列以查看要过滤的内容。