【问题标题】:Select every row from every table in database where (columnName = value) if column name exists如果列名存在,则从数据库中的每个表中选择每一行,其中 (columnName = value)
【发布时间】:2010-12-03 21:40:53
【问题描述】:

我使用的是 SQL Server 2005,并以sa 登录。我想查询数据库中的每个表是否有某个列名。如果是这样,将 (columnNameValue = someValue) 的每一行附加到结果表中。然后返回所述结果表。

解决方案存在一些类似的问题。值得注意的是,我可以为此使用sp_MSForeachTable,但它缺少任何类型的文档。我可以使用SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES 来获取所有表的列表。

以下解决方案 (link text) 将遍历每个表和每列以在单元格中找到某个值。这与如果该列是某个 columnName 在单元格中查找某个值不同。

应该可以编写嵌套的 while 语句,但是否有任何内置命令来运行这样的查询?

如果有帮助,请使用伪代码:

foreach(table in tableList) {
    if (table.hasColumnName(SOME_COLUMN) {
       EXEC ('SELECT * FROM table WHERE (SOME_COLUMN = SOME_VALUE)')
    }
}

[编辑]

只要选择返回至少一行,我希望每个表都有一个结果集,而不是只有一个结果集。这应该会产生大量不同的结果,因为期望 join 或 union 起作用是不现实的。

如果可能,我想将表名附加到每个结果的开头。

我在下面有一个简单的查询,它可以获取所有结果,但它会显示空表,并且不会在单个结果中给出任何关于它属于哪个表的视觉指示:

[进一步编辑]

更新了下面的查询以包括删除 NULL 结果的 IF EXIST 检查和选择名称 AS 源列,以将表源添加到结果中,感谢 @Martin

DECLARE @COLUMN_VALUE nvarchar(512), @VALUE nvarchar(10);

SET @COLUMN_VALUE = 'id'
SET @VALUE = '0';

DECLARE @TABLE_NAME nvarchar(512), @COLUMN_NAME nvarchar(512), @QUERY nvarchar(512);

SET @TABLE_NAME = '';

WHILE @TABLE_NAME IS NOT NULL
BEGIN
    SET @TABLE_NAME =
    (
        SELECT MIN(QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME))
        FROM INFORMATION_SCHEMA.TABLES
        WHERE QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME) > @TABLE_NAME
    );
    PRINT 'Table name : ' + @TABLE_NAME;
    SET @COLUMN_NAME = 
    (
        SELECT MIN(QUOTENAME(COLUMN_NAME))
        FROM INFORMATION_SCHEMA.COLUMNS
        WHERE (TABLE_NAME = PARSENAME(@TABLE_NAME, 1))
            AND (COLUMN_NAME = @COLUMN_VALUE)

    );
    PRINT 'Column name : ' + @COLUMN_NAME;
    IF @COLUMN_NAME IS NOT NULL 
    BEGIN
        SET @QUERY = 
            'SELECT ''' + @TABLE_NAME + ''' AS Source, * ' +
            'FROM ' + @TABLE_NAME + ' ' +
            'WHERE (' + @COLUMN_NAME + ' = ' + @VALUE + ')'
        EXEC
        (
            'IF EXISTS(' + @QUERY + ') ' + @QUERY
        )
    END     
END

【问题讨论】:

  • 如果 TableA 有两列而 TableB 有三列,您希望发生什么?
  • @Lieven 没有必要将所有结果合并到一个表中,因为它非常不可读,因此为每个表示 columnName 有效的表返回一个结果集。

标签: sql sql-server-2005 tsql


【解决方案1】:
CREATE TABLE foo
(
SOME_COLUMN VARCHAR(10)
)

CREATE TABLE bar
(
SOME_COLUMN VARCHAR(10)
)

INSERT INTO bar VALUES ('SOME_VALUE')


DECLARE @Query nvarchar(max)

SELECT 
      @Query = isnull(@Query + ';','') + 
      'IF EXISTS(SELECT * FROM ' + QUOTENAME(SCHEMA_NAME(schema_id)) + '.' + 
      QUOTENAME(o.name) + ' WHERE SOME_COLUMN=''SOME_VALUE'')
      SELECT ''' + o.name +''' AS Source, * FROM ' + QUOTENAME(SCHEMA_NAME(schema_id)) + '.' + 
      QUOTENAME(o.name) + ' WHERE SOME_COLUMN=''SOME_VALUE'''
FROM sys.columns c 
JOIN sys.objects o
ON o.object_id = c.object_id
WHERE o.type IN ('U','V') AND c.name = 'SOME_COLUMN'

EXEC sp_executesql @Query

【讨论】:

  • 您能澄清一下schema_idobject_id 应该是什么吗?我意识到要求结果集是一个包含很多列的大型 JOIN 是没有用的。
  • 不确定您的意思?这些是sys.tables中的列
  • 它为我抛出了sql-server-performance.com/faq/… 错误。我忘了提到没有保证所有表都会在其中说出列名。
  • @Martin,我认为用 GO; 替换 UNION ALL 会更好。只有所有表都具有相同的列定义(显然它们没有),UNION 才会起作用。之后如何将其插入到另一个表中至少可以说是棘手的。
  • foobar 只是演示表。对不起,不知道为什么你会得到不同的结果。你必须自己解决这个问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-14
  • 1970-01-01
  • 1970-01-01
  • 2018-05-04
  • 2023-03-31
  • 1970-01-01
相关资源
最近更新 更多