如何使用表名称变量通过SQL查询大表列表?

时间:2018-07-05 19:47:41

标签: sql oracle plsql

我对在多个表上运行Oracle DB查询有疑问。有没有一种方法可以使表名变量迭代,而不必声明每个表名?

背景示例

  1. 有大量的表(例如TABLE_1 ... TABLE_100)。
  2. 每个表都列在另一个表(例如TABLE_LIST)的NAME列中,该表列出了更多的表以及TYPE(例如“帐户”)
  3. 这些表中的每个表的VALUE列均是一个布尔列“ ACTIVE”。

要求

  1. 通过TYPE ='Account'查询TABLE_LIST
  2. 对于找到的每个表,在该表中查询所有活动记录,其中列ACTIVE ='N'
  3. 结果显示每个表行中的表NAME和VALUE,其中ACTIVE ='N'。

任何提示将不胜感激。

2 个答案:

答案 0 :(得分:1)

科技含量低,高科技含量高。我将它们分开回答,以便人们可以为它们投票。这是高科技版本。

设置:与低技术版本相同。

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

答案 1 :(得分:0)

科技含量低,高科技含量高。我将它们分开回答,以便人们可以为它们投票。这是技术含量较低的版本。

设置:

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