ORA-00904 и ORA-06512, когда я пытаюсь максимально увеличить все столбцы - PullRequest
0 голосов
/ 26 мая 2020
create or replace PROCEDURE COMPARAISON_TEST as

begin
 declare

cursor c_tab is
select table_name, column_name , data_type 
from all_tab_columns;

  v_sql VARCHAR2 (32000);

        begin  

            FOR r_tab in c_tab LOOP     
            v_sql := 'SELECT ' || 
            r_tab.table_name || ' TABLE_NAME, ' || 
            r_tab.column_name || ' COLUMN_NAME, ' || 
            '(SELECT MAX(' || r_tab.column_name || ') FROM ' || r_tab.table_name || ') VALUE ' || 
            'FROM DUAL ';
    execute immediate v_sql;
end LOOP;
end;  
end COMPARAISON_TEST;

ОШИБКИ

   ORA-00904: "DUAL" : invalid identifier   
   ORA-06512: à "ODS.COMPARAISON_TEST", line 20    
   ORA-06512: à "ODS.COMPARAISON_TEST", line 20    
   ORA-06512: à line 2

Ответы [ 2 ]

0 голосов
/ 27 мая 2020

Вы должны заключить в двойные одинарные кавычки, которые вы хотите разместить в строке.

v_sql := 'SELECT ''' || 
            r_tab.table_name || ''' TABLE_NAME, ''' || 
            r_tab.column_name || ''' COLUMN_NAME, ' || 
            '(SELECT MAX(' || r_tab.column_name || ') FROM ' || r_tab.table_name || ') VALUE ' || 
            'FROM DUAL ';
0 голосов
/ 26 мая 2020

Проблема в том, что вы делаете это в темноте .

Всегда, перед фактическим выполнением Dynami c SQL, отображать на экран, чтобы вы увидели строку, которую нужно выполнить.

Это то, что вы сделали (я добавил к курсору предложение WHERE, чтобы сократить вывод):

SQL>  declare
  2
  3  cursor c_tab is
  4  select table_name, column_name , data_type
  5  from all_tab_columns
  6  where owner = 'SCOTT' and table_name = 'DEPT';
  7
  8    v_sql VARCHAR2 (32000);
  9
 10          begin
 11
 12              FOR r_tab in c_tab LOOP
 13              v_sql := 'SELECT ' ||
 14              r_tab.table_name || ' TABLE_NAME, ' ||
 15              r_tab.column_name || ' COLUMN_NAME, ' ||
 16              '(SELECT MAX(' || r_tab.column_name || ') FROM ' || r_tab.table_name || ') VALUE ' ||
 17              'FROM DUAL ';
 18      dbms_output.put_line(v_sql);
 19      --execute immediate v_sql;
 20  end LOOP;
 21  end;
 22  /
SELECT DEPT TABLE_NAME, DEPTNO COLUMN_NAME, (SELECT MAX(DEPTNO) FROM DEPT) VALUE
FROM DUAL
SELECT DEPT TABLE_NAME, DNAME COLUMN_NAME, (SELECT MAX(DNAME) FROM DEPT) VALUE
FROM DUAL
SELECT DEPT TABLE_NAME, LOC COLUMN_NAME, (SELECT MAX(LOC) FROM DEPT) VALUE FROM
DUAL

PL/SQL procedure successfully completed.

SQL>

Видите все эти недопустимые строки? Их нельзя казнить. Чтобы сделать их действительными, включите имена таблиц и столбцов в одинарные кавычки, например

SELECT 'DEPT' TABLE_NAME, 'DEPTNO' COLUMN_NAME, (SELECT MAX(DEPTNO) FROM DEPT) VALUE
FROM DUAL;

Это то, что вы могли бы захотеть:

SQL> set serveroutput on
SQL>
SQL> declare
  2    cursor c_tab is
  3      select table_name, column_name , data_type
  4      from user_tab_columns
  5      where table_name = 'DEPT';
  6    v_sql VARCHAR2 (32000);
  7    v_val varchar2(200);
  8  begin
  9    FOR r_tab in c_tab LOOP
 10      v_sql := 'SELECT MAX(' || r_tab.column_name || ') FROM ' ||
 11                r_tab.table_name;
 12      execute immediate v_sql into v_val;
 13      dbms_output.put_line(r_tab.table_name||'.'||r_tab.column_name||': '|| v_val);
 14    end LOOP;
 15  end;
 16  /
DEPT.DEPTNO: 40
DEPT.DNAME: SALES
DEPT.LOC: NEW YORK

PL/SQL procedure successfully completed.

SQL>

Если вы хотите сохранить результат в таблице, тогда вы должны сделать что-то вроде этого:

SQL> create table maxes
  2    (table_name   varchar2(30),
  3     column_name  varchar2(30),
  4     max_value    varchar2(30)
  5    );

Table created.

SQL> declare
  2    cursor c_tab is
  3      select table_name, column_name , data_type
  4      from user_tab_columns
  5      where table_name = 'DEPT';
  6    v_sql VARCHAR2 (32000);
  7    v_val varchar2(200);
  8  begin
  9    FOR r_tab in c_tab LOOP
 10      v_sql := 'SELECT MAX(' || r_tab.column_name || ') FROM ' ||
 11                r_tab.table_name;
 12      execute immediate v_sql into v_val;
 13      insert into maxes (table_name, column_name, max_value)
 14        values
 15        (r_tab.table_name, r_tab.column_name, v_val);
 16    end LOOP;
 17  end;
 18  /

PL/SQL procedure successfully completed.

SQL> select * From maxes;

TABLE_NAME      COLUMN_NAME     MAX_VALUE
--------------- --------------- ---------------
DEPT            DEPTNO          40
DEPT            DNAME           SALES
DEPT            LOC             NEW YORK

SQL>
...