【问题标题】:Display result from loop tables (oracle, pl/sql)显示循环表的结果(oracle、pl/sql)
【发布时间】:2018-08-09 11:00:26
【问题描述】:

我正在尝试循环一些表并运行如下选择:

set serveroutput on
declare

type tables_names is table of varchar2(30);
type selectTable is table of varchar2(30);

tName tables_names;
sTableName selectTable;

begin;

tName := tables_names('PERIOD','SETTING','RAP','LOG');
sTableName := selectTable('m_table1','m_table2','m_table3','m_table4','m_table5');    

    for i in 1..tName.count loop
        for j in 1..sTableName.count loop

               select col10, count(*) from user.sTableName(j) 
               where table_name = tName(i) group by col10;            

        end loop;
    end loop;

end;

我收到错误:PL/SQL: ORA-00933。

您能否告诉我如何正确运行 PL/SQL 程序以显示我选择的结果?

更新:查看结果

通常,为了得到这个,我需要在 select 下运行:

select column_name, 
count(*) as countColumn
from user.m_table1 where table_name = 'PERIOD' group by column_name;

select column_name, 
count(*) as countColumn
from user.m_table2 where table_name = 'PERIOD' group by column_name;

【问题讨论】:

    标签: sql oracle loops plsql oracle12c


    【解决方案1】:

    Oracle 抱怨 (ORA-00933) 命令未正确结束。这可能是因为 BEGIN 后面有一个分号;另外,您缺少 INTO 子句。

    我不确定 PERIOD、SETTING、... 与 m_table1、m_table2、... 哪些是表名?那么,其他值是什么?

    无论如何:这是一个示例,它显示了如何执行类似的操作 - 从表中计算行数。尝试根据您的情况进行调整,或者 - 可能 - 添加更多信息,以便我们知道您在做什么。

    SQL> set serveroutput on
    SQL> declare
      2    tname   sys.odcivarchar2list := sys.odcivarchar2list();
      3    l_cnt   number;
      4    l_str   varchar2(200);
      5  begin
      6    tname := sys.odcivarchar2list('EMP', 'DEPT');
      7
      8    for i in 1 .. tname.count loop
      9      l_str := 'select count(*) from ' || tname(i);
     10      execute immediate l_str into l_cnt;
     11      dbms_output.put_line(tname(i) ||': '|| l_cnt);
     12    end loop;
     13  end;
     14  /
    EMP: 14
    DEPT: 4
    
    PL/SQL procedure successfully completed.
    
    SQL>
    

    [编辑:添加 GROUP BY 选项]

    给你;由于 EMP 和 DEPT 共享 DEPTNO 列,我选择它作为 GROUP BY 列。

    SQL> declare
      2    tname   sys.odcivarchar2list := sys.odcivarchar2list();
      3    type    t_job is record (deptno varchar2(20), cnt number);
      4    type    t_tjob is table of t_job;
      5    l_tjob  t_tjob := t_tjob();
      6    l_str   varchar2(200);
      7  begin
      8    tname := sys.odcivarchar2list('EMP', 'DEPT');
      9
     10    for i in 1 .. tname.count loop
     11      l_str := 'select deptno, count(*) from ' || tname(i) ||' group by deptno';
     12      execute immediate l_str bulk collect into l_tjob;
     13
     14      for j in l_tjob.first .. l_tjob.last loop
     15        dbms_output.put_Line('Table ' || tname(i) || ': Deptno ' || l_tjob(j).deptno||
     16          ': number of rows = '|| l_tjob(j).cnt);
     17      end loop;
     18
     19    end loop;
     20  end;
     21  /
    Table EMP: Deptno 30: number of rows = 6
    Table EMP: Deptno 20: number of rows = 5
    Table EMP: Deptno 10: number of rows = 3
    Table DEPT: Deptno 10: number of rows = 1
    Table DEPT: Deptno 20: number of rows = 1
    Table DEPT: Deptno 30: number of rows = 1
    Table DEPT: Deptno 40: number of rows = 1
    
    PL/SQL procedure successfully completed.
    
    SQL>
    

    【讨论】:

    • 什么分组?表(通常)不共享列名。我会根据什么对 EMP 进行分组?和部门?别的表? DEPT 包含 3 列 - 其中之一应在 GROUP BY 子句中使用。 EMP 包含 8 列。应该使用哪一种?
    • 按其他列分组,因为我需要显示数字(count = l_cnt)和值(列),请以 EMP 表中的列之一为例
    • 是的,但是还有哪一列?对于 EMP 表:EMPNO?姓名?萨尔?工作?经理? DEPTNO?
    • 可以是Job,没关系,我只想看看语法
    • 好的,明白了;这是您正在寻找的原则。我通过添加 GROUP BY 选项来编辑我的答案。看看吧。
    【解决方案2】:

    您可能正在寻找类似的东西。请注意,如果没有INTO 子句,您将无法在 PL/SQL 中运行简单的选择语句。使用refcursorDBMS_SQL.RETURN_RESULT

    DECLARE
       TYPE tables_names IS TABLE OF VARCHAR2 (30);
    
       TYPE selectTable IS TABLE OF VARCHAR2 (30);
    
       tName        tables_names;
       sTableName   selectTable;
       rc           SYS_REFCURSOR;
    BEGIN
       tName :=
          tables_names ('PERIOD',
                        'SETTING',
                        'RAP',
                        'LOG');
       sTableName :=
          selectTable ('m_table1',
                       'm_table2',
                       'm_table3',
                       'm_table4',
                       'm_table5');
    
       FOR i IN 1 .. tName.COUNT
       LOOP
          FOR j IN 1 .. sTableName.COUNT
          LOOP
             OPEN rc FOR
                   'select col10, count(*) from '||USER||'.'
                || sTableName (j)
                || ' where table_name = '''
                || tName (i)
                || ''' group by col10';
    
             DBMS_SQL.RETURN_RESULT (rc);
    
          END LOOP;
       END LOOP;
    END;
    /
    

    【讨论】:

    • 可以更好地格式化它吗?喜欢一行一行?
    • @4est :我在 cmets 中要求您在问题中显示预期的输出。你为什么不编辑你的问题并说出你想看到的输出呢?
    • @4est:很遗憾,由于限制,我无法加载您的图片。但是,我认为我给你的解决方案应该可以很好地获得预期的结果。请测试,如果你没有,请告诉我
    • 你可以检查我通常运行的两个选择以获得结果,现在我想让它循环
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-20
    • 1970-01-01
    • 2016-08-03
    • 2023-04-01
    相关资源
    最近更新 更多