读取 SQL 表中的列,这些列是另一个查询的结果

Read columns in SQL tables which are the result of another query

我需要检查所有 主键 列的 所有值都是大写的

所以,我有第一个请求,returns 我 table-字段对,它们是 PK 的一部分。

SELECT table_name, field_name FROM dico WHERE pkey > 0;

(dico 是一些 table,它提供了该信息。无需在 SQL 模式中查找它……)

并且,对于上面第一个查询中列出的所有那些 tx/fx 对,我需要查找不会大写的值。

SELECT DISTINCT 't1', 'f1', f1 FROM t1 WHERE f1 <> UPPER(f1) UNION ALL
SELECT DISTINCT 't2', 'f2', f2 FROM t2 WHERE f2 <> UPPER(f2) UNION ALL
...
SELECT DISTINCT 'tn', 'fn', fn FROM tn WHERE fn <> UPPER(fn);

(我在输出中将 table 名称和字段名称作为“字符串”,以便我知道错误值的来源。)

如您所见,我确实有这两个请求的代码,但我不知道如何将它们组合起来(如果可能,以一种适用于 SQL Server 和 Oracle 的通用方式)。

你能告诉我如何完成它吗?

我能想到的一种方法是使用包含循环的语句块。

不幸的是,语句块的结构对于每个不同的数据库系统都是不同的(SQL Server 的语句块对于 Oracle 是不同的)。

我在下面使用 SQL 服务器编写了一个示例(fiddle link 位于:https://dbfiddle.uk/?rdbms=sqlserver_2017&fiddle=85cd786adf32247da1aa73c0341d1b72)。

以防万一,动态查询变得很长(可能超过 varchar 的限制,即 8000 个字符),SQL 服务器有 varchar(max) 可以支持到 2GB (https://docs.microsoft.com/en-us/sql/t-sql/data-types/char-and-varchar-transact-sql?view=sql-server-ver15). This can be used for @DynamicQuery, replacing VARCHAR(3000) in the example below (modified/alternative fiddle link, just to show that the data type really exists and can be used, is at: https://dbfiddle.uk/?rdbms=sqlserver_2017&fiddle=7fbb5d130aad35e682d8ce7ffaf09ede).

请注意,该示例未使用您的确切查询,因为我无法访问与您拥有的完全相同的数据(例如,我无法使用 dico table 测试该示例因为我无法访问那个 table)。 但是,我制作了这个示例,以便它使用与您的查询相似的基本逻辑结构,以便稍后可以对其进行自定义以适合您的确切 need/scenario(例如,通过更改 table 名称和字段名称以匹配您使用的名称,以及根据需要添加 WHERE 子句)。

在示例中,您的第一个查询将立即 运行,结果将由游标处理。

之后,一个循环(使用 WHILE statement/structure)将循环遍历游标以获取第一个查询的结果以动态构建第二个查询(插入 table 名称以及第一个查询中的字段名称)。

请注意,此时,第二个查询仍在构建中,尚未 运行。

最终,在循环结束后,resulting/compiled 第二个查询将是 run/executed(使用 EXEC 命令)。

-- START of test data creation.
create table TableA
( message varchar(200)
);

insert into TableA([message]) values ('abc');
insert into TableA([message]) values ('def');

create table TableB
( message varchar(200)
);

insert into TableB([message]) values ('ghi');
insert into TableB([message]) values ('jkl');
-- END of test data creation.



-- START of dynamic SQL
declare @TableAndFieldDetails CURSOR
declare @TableName VARCHAR(50)
declare @FieldName VARCHAR(50)
declare @DynamicQuery VARCHAR(3000) = ''
begin
  SET @TableAndFieldDetails = CURSOR FOR
  -- START of the 1st query
  SELECT  [INFORMATION_SCHEMA].COLUMNS.TABLE_NAME,
          [INFORMATION_SCHEMA].COLUMNS.COLUMN_NAME
  FROM    INFORMATION_SCHEMA.COLUMNS
  WHERE   INFORMATION_SCHEMA.COLUMNS.COLUMN_NAME LIKE '%message%'
  -- END of the 1st query

  -- START of dynamically building the 2nd query
  OPEN @TableAndFieldDetails
  FETCH NEXT FROM @TableAndFieldDetails INTO @TableName, @FieldName
  WHILE @@FETCH_STATUS = 0
  BEGIN
    IF @DynamicQuery <> ''
    BEGIN
      SET @DynamicQuery += ' UNION ALL '
    END

    -- The one line right below is each individual part/element of the 2nd query
    SET @DynamicQuery += 'SELECT ''' + @TableName + ''', ''' + @FieldName + ''', ' + @FieldName + ' FROM ' + @TableName

    FETCH NEXT FROM @TableAndFieldDetails INTO @TableName, @FieldName
  END
  CLOSE @TableAndFieldDetails
  DEALLOCATE @TableAndFieldDetails
  -- END of dynamically building the 2nd query

  EXEC (@DynamicQuery)
end
-- END of dynamic SQL