Как объявить курсор, если таблица, используемая в операторе выбора, может иногда не существовать? - PullRequest
0 голосов
/ 04 мая 2020

Мне нужно запустить приведенный ниже код в разных средах, и он отлично работает, когда table1 существует, но когда он не существует, он выдает ошибку в объявлении курсора, что «таблица или представление не существует». Я запускаю это на Oracle. Не могли бы вы помочь мне исправить это? Заранее спасибо.

DECLARE
CURSOR my_cursor IS (select "col1" from "table1");
name1 VARCHAR2(256);
tableCount NUMBER;
BEGIN
Select count(*) into tableCount from user_tab_cols where table_name = 'table1' and column_name = 'col2';
IF tableCount > 0 THEN
OPEN my_cursor;
LOOP
FETCH my_cursor into name1;
EXIT WHEN my_cursor%notfound;
-- Update or delete statement here
DBMS_OUTPUT.PUT_LINE('value is ' || name1);
END LOOP;
CLOSE my_cursor;
END IF;
END;
/

Ответы [ 2 ]

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

CURSOR с определенным типом возврата строго типизирован. Sys_refcursors слабо типизированы. Это означает, что любой тип возвращаемого значения в CURSOR должен быть действительным. SYS_REFCURSOR является более гибким и может быть определен позднее.

При установке CURSOR в разделе объявлений необходимо использовать оператор SQL, который будет выполняться правильно. В этом случае вы устанавливаете CURSOR для выбора столбца из таблицы, которая не существует. Выполнение базы данных не достигнет тела кода, так как оно вызывает ошибки до выхода из блока объявления.

Чтобы исправить это, используйте SYS_REFCURSOR с динамическим c sql запросом, как упомянуто Teja sh выше. Это позволяет проверить, существует ли таблица, перед установкой курсора. Если таблица существует, установите курсор для выбора из указанной таблицы. Если этого не произойдет, выведите сообщение о том, что его не существует.

Обратите внимание, что вы также можете использовать коды ошибок SQL, как показано в других ответах. Я предпочитаю лично обрабатывать бизнес-правила в логи c до возникновения ошибки.

DECLARE
 my_cursor sys_refcursor;
name1 VARCHAR2(256);
tableCount NUMBER;
BEGIN
Select count(*) into tableCount from user_tab_cols where table_name = 'table1' and column_name = 'col2';
IF tableCount > 0 THEN
OPEN my_cursor for 'select order_id from table1';
LOOP
FETCH my_cursor into name1;
EXIT WHEN my_cursor%notfound;
-- Update or delete statement here
DBMS_OUTPUT.PUT_LINE('value is ' || name1);
END LOOP;
CLOSE my_cursor;
else
dbms_output.put_line('Table does not exist');
END IF;
END;

http://docs.oracle.com/database/122/LNPLS/static-sql.htm#LNPLS568

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

Вы можете использовать exceptions и dynamic string для курсора следующим образом:

DECLARE
    MY_CURSOR    SYS_REFCURSOR;
    NAME1        VARCHAR2(256);
    TABLECOUNT   NUMBER;
BEGIN
    OPEN MY_CURSOR FOR 'SELECT ACC_NR FROM ACCOUNT'; -- dynamic string for cursor

    LOOP
        FETCH MY_CURSOR INTO NAME1;
        EXIT WHEN MY_CURSOR%NOTFOUND;
        DBMS_OUTPUT.PUT_LINE('value is ' || NAME1);
    END LOOP;

    CLOSE MY_CURSOR;
EXCEPTION -- exception handling using SQLCODE
    WHEN OTHERS THEN
        IF SQLCODE = -942 THEN
            DBMS_OUTPUT.PUT_LINE('Table does not exists');
        ELSIF SQLCODE = -904 THEN
            DBMS_OUTPUT.PUT_LINE('Invalid column name');
        ELSE
            DBMS_OUTPUT.PUT_LINE('Other error');
        END IF;
END;
/
...