На днях возникла простенькая, но нестандартная задачка. Как грамотно отловить ошибку 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;