Можем ли мы найти, какая таблица вызывает ORA-00942, таблица или представление не существует .: - PullRequest
1 голос
/ 02 мая 2019

У меня есть нормальный блок PLSQL с запросом CTAS.

BEGIN
EXECUTE IMMEDIATE'
CREATE TABLE ZZZ_TEMP NOLOGGING PARALLEL AS
SELECT /*+ PARALLEL(a,4) */
        *
    FROM
        HI0XXX001.HI_TABLE_NAME a
    LEFT JOIN
        HR_001_GROUP B
    ON
        a.EMPLOYERGROUP_UD =B.ACC_NUM
    LEFT JOIN
        HR_002_GROUP l
    ON
        a.EMPLOYERGROUP_UD =l.EMPLOYERGROUP_UD
    AND
        a.GRP_CON_UD_COV_CONTRACT_NAME=l.GRP_CON_UD_COV_CONTRACT_NAME
    ';
EXCEPTION WHEN OTHERS THEN Dbms_Output.put_line(SQLERRM);
END;

Предположим, что таблица HR_002_GROUP не существует в схеме, где я запускаю этот блок. Есть ли способ показать сообщение об ошибке, в котором говорится, что таблица HR_002_GROUP не существует?

Отправленный мной запрос - всего лишь пример сценария. Мы работаем в структуре ETL, и у нас есть большая строка сценария запроса, который вставляет миллионы данных из одной из многих таблиц HI в другую небольшую таблицу с префиксом VH. У меня около 15-30 столов в левом соединении. Выбор каждого левого соединения занимает много времени, чтобы узнать, какая таблица на самом деле вызывает ошибку.

1 Ответ

4 голосов
/ 03 мая 2019

Используйте DBMS_SQL вместо собственного динамического SQL, а затем используйте DBMS_SQL.LAST_ERROR_POSITION() для идентификации части оператора с ошибкой.

DBMS_SQL менее удобно, чем собственный динамический SQL, но такжеболее могущественный.Есть несколько ошибок, на которые стоит обратить внимание.Во-первых, процедура DBMS_SQL.PARSE не только анализирует команды, но и автоматически запускает команды DDL.

Приведенный ниже код пытается создать таблицу с использованием двух других таблиц, одна из которых, очевидно, не существует.,Регулярное выражение используется для вывода каждого символа с позиции ошибки в первый пробел.(Этот код основан на этом ответе. )

declare
    v_cursor_id integer := dbms_sql.open_cursor ();
    v_sql varchar2(32767) := q'[
        create table zzz_temp as
        select *
        from dual
        join some_schema.fake_table
            on dual.dummy = fake_table.dummy
    ]';
begin
    dbms_sql.parse(v_cursor_id, v_sql, dbms_sql.native);
    dbms_sql.close_cursor(v_cursor_id);
exception
    when others then
        dbms_output.put_line
        (
            sqlerrm||chr(10)||
            'Error occurred here: '||
            regexp_substr
            (
                srcstr   => v_sql,
                pattern  => '\w+',
                position => dbms_sql.last_error_position()
            )
        );
        dbms_sql.close_cursor(v_cursor_id);
end;
/

DBMS_OUTPUT:

ORA-00942: table or view does not exist
Error occurred here: fake_table

Некоторые другие предложения случайных кодов:

  1. Используйте PARALLEL(4) вместо PARALLEL(A, 4).Параллелизм на уровне операторов почти всегда лучше параллелизма на уровне объектов.Если вы запустите одну таблицу параллельно, вы, вероятно, захотите выполнить весь запрос параллельно.
  2. Старайтесь избегать WHEN OTHERS.Если возможно, используйте более конкретный обработчик ошибок.
...