如何使用表名变量SQL查询大型表列表?

如何使用表名变量SQL查询大型表列表?,sql,oracle,plsql,Sql,Oracle,Plsql,我有一个关于在多个表上运行Oracle DB查询的问题。有没有一种方法可以使表名变量进行迭代,而不是必须声明每个表名 背景示例 有大量的表格(例如表格1…表格100) 这些表中的每一个都列在另一个表的名称列中(例如,table_LIST),列出了更多的表以及类型(例如“Account”) 这些表中的每个表都有ColumnValue一个布尔列,处于活动状态 要求 按类型='Account'查询表\u列表 对于找到的每个表,查询该表中列活动='N'的所有记录 结果显示ACTIVE='N'所在的每个表

我有一个关于在多个表上运行Oracle DB查询的问题。有没有一种方法可以使表名变量进行迭代,而不是必须声明每个表名

背景示例
  • 有大量的表格(例如表格1…表格100)
  • 这些表中的每一个都列在另一个表的名称列中(例如,table_LIST),列出了更多的表以及类型(例如“Account”)
  • 这些表中的每个表都有ColumnValue一个布尔列,处于活动状态
  • 要求
  • 按类型='Account'查询表\u列表
  • 对于找到的每个表,查询该表中列活动='N'的所有记录
  • 结果显示ACTIVE='N'所在的每个表行的表名和值

  • 任何提示都将不胜感激。

    有低技术和高技术两种方式。我会把它们放在不同的答案中,这样人们就可以投他们的票。这是低技术版本

    CREATE TYPE my_row AS OBJECT (name VARCHAR2(128), value NUMBER)
    /
    CREATE TYPE my_tab AS TABLE OF my_row
    /
    
    CREATE OR REPLACE FUNCTION my_fun RETURN my_tab PIPELINED IS
      rec my_row := my_row(null, null);
      cur SYS_REFCURSOR;
    BEGIN
      FOR t IN (SELECT name FROM table_list WHERE table_type='Account') LOOP
        rec.name  := dbms_assert.sql_object_name(t.name);
        OPEN cur FOR 'SELECT value FROM '||t.name||' WHERE active=''N''';
        LOOP
          FETCH cur INTO rec.value;
          EXIT WHEN cur%NOTFOUND;
          PIPE ROW(rec);      
        END LOOP;
        CLOSE cur;
      END LOOP;
    END my_fun;
    /
    
    SELECT * FROM TABLE(my_fun);
    
    NAME     VALUE
    TABLE_1      1
    TABLE_3      3
    
    设立:

    CREATE TABLE table_1 (value NUMBER, active VARCHAR2(1) CHECK(active IN ('Y','N')));
    CREATE TABLE table_2 (value NUMBER, active VARCHAR2(1) CHECK(active IN ('Y','N')));
    CREATE TABLE table_3 (value NUMBER, active VARCHAR2(1) CHECK(active IN ('Y','N')));
    INSERT INTO table_1 VALUES (1, 'N');
    INSERT INTO table_1 VALUES (2, 'Y');
    INSERT INTO table_3 VALUES (3, 'N');
    INSERT INTO table_3 VALUES (4, 'Y');
    
    CREATE TABLE table_list (name VARCHAR2(128 BYTE) NOT NULL, table_type VARCHAR2(10)); 
    INSERT INTO  table_list (name, table_type) VALUES ('TABLE_1', 'Account');
    INSERT INTO  table_list (name, table_type) VALUES ('TABLE_2', 'Something');
    INSERT INTO  table_list (name, table_type) VALUES ('TABLE_3', 'Account');
    
    快速简便的方法是使用一个查询生成另一个查询。我经常这样做,尤其是一次性工作:

    SELECT 'SELECT '''||name||''' as name, value FROM '||name||
           ' WHERE active=''N'' UNION ALL' as sql  
      FROM table_list 
     WHERE table_type='Account';
    
    SELECT 'TABLE_1' as name, value FROM TABLE_1 WHERE active='N' UNION ALL
    SELECT 'TABLE_3' as name, value FROM TABLE_3 WHERE active='N' UNION ALL
    
    您必须删除最后一个
    UNION ALL
    ,然后执行查询的其余部分。结果是

    NAME     VALUE
    TABLE_1      1
    TABLE_3      3
    

    有低技术和高技术两种方式。我会把它们放在不同的答案中,这样人们就可以投他们的票。这是高科技版本

    CREATE TYPE my_row AS OBJECT (name VARCHAR2(128), value NUMBER)
    /
    CREATE TYPE my_tab AS TABLE OF my_row
    /
    
    CREATE OR REPLACE FUNCTION my_fun RETURN my_tab PIPELINED IS
      rec my_row := my_row(null, null);
      cur SYS_REFCURSOR;
    BEGIN
      FOR t IN (SELECT name FROM table_list WHERE table_type='Account') LOOP
        rec.name  := dbms_assert.sql_object_name(t.name);
        OPEN cur FOR 'SELECT value FROM '||t.name||' WHERE active=''N''';
        LOOP
          FETCH cur INTO rec.value;
          EXIT WHEN cur%NOTFOUND;
          PIPE ROW(rec);      
        END LOOP;
        CLOSE cur;
      END LOOP;
    END my_fun;
    /
    
    SELECT * FROM TABLE(my_fun);
    
    NAME     VALUE
    TABLE_1      1
    TABLE_3      3
    
    设置:与低技术版本相同

    CREATE TYPE my_row AS OBJECT (name VARCHAR2(128), value NUMBER)
    /
    CREATE TYPE my_tab AS TABLE OF my_row
    /
    
    CREATE OR REPLACE FUNCTION my_fun RETURN my_tab PIPELINED IS
      rec my_row := my_row(null, null);
      cur SYS_REFCURSOR;
    BEGIN
      FOR t IN (SELECT name FROM table_list WHERE table_type='Account') LOOP
        rec.name  := dbms_assert.sql_object_name(t.name);
        OPEN cur FOR 'SELECT value FROM '||t.name||' WHERE active=''N''';
        LOOP
          FETCH cur INTO rec.value;
          EXIT WHEN cur%NOTFOUND;
          PIPE ROW(rec);      
        END LOOP;
        CLOSE cur;
      END LOOP;
    END my_fun;
    /
    
    SELECT * FROM TABLE(my_fun);
    
    NAME     VALUE
    TABLE_1      1
    TABLE_3      3
    

    是的,您可以将表名放入临时表中,并在其上定义一个光标以进行循环。您还将有一个动态SQL字符串,该字符串被参数化以插入当前表名。Stackoverflow不是一个代码编写服务。向我们展示您编写的代码,无论您是否面临任何问题或错误?另外,“N”不是布尔值,它是一个字符。为避免混淆,请务必为您的示例显示一些示例输出。我将添加使用
    dbms\u assert.sql\u object\u name(t.name)
    检查表名的功能,以降低sql注入的风险。以防万一:)