На днях возникла простенькая, но нестандартная задачка. Как грамотно отловить ошибку ORA-00942 “Таблица или представление не существует” в обычном PL/SQL блоке при попытке выполнения любой команды DML? Ну есть 2 класса пользователей, одни имеют разрешение на изменение таблицы, другие – нет. Но, т.к. весь блок состоит из нескольких операций, не хотелось создавать копии, отличающиеся одной командой, а разобраться на месте в самом блоке. Ошибка возникает на стадии лексического разбора, поэтому до обработки исключений дело не доходит. Решить такую задачу помогает динамический SQL.
declare
< необходимые объявления>
begin
< различные операции>
-- начало вложенного блока обработки выполнения DML
declare
-- создаем и открываем курсор
cr int := dbms_sql.open_cursor;
v_rows int;
-- тот самый запрос, который может вызвать ошибку из-за отсутствия видимости (допустим, удалить запись с заданным идентификатором)
v_sql varchar2(32767) := 'delete from my_table where ID = :p_id';
begin
-- лексический разбор заданной команды
dbms_sql.parse(cr, v_sql, dbms_sql.native);
-- если в запросе есть связанные переменные, присваиваем им значения (в нашем примере переменная p_id)
DBMS_SQL.BIND_VARIABLE(cf, ':p_id', 100);
-- выполнение запроса
v_rows := DBMS_SQL.EXECUTE(cf);
-- не забываем закрыть курсор
dbms_sql.close_cursor (cf);
-- обработка ошибки
exception when OTHERS then
-- после отлавливания любой ошибки проверяем ее код, если это ожидаемая
-- нами ORA-00942, ничего не делаем или, наоборот, выполняем какие-то обработчики,
-- в случае любой другой ошибки вызываем ее заново
if SQLCODE = -942 then
null;
else
raise;
end if;
end;
end;
