Поэтому я сделал ошибку, из-за которой я не помещал немедленное выполнение во вложенный блок начала-конца, поэтому мой код не работал. Так что в основном у меня было
begin
execute immediate 'select * from sales';
exception when others then null;
dbms_output.put_line(123);
end;
Dbms_output не напечатал «123», и я понял, что мне нужно поместить немедленное выполнение в начало-конец. Я хочу быть уверен, поэтому мой вопрос: почему код не выполняется после части исключения, даже если исключение не возникает?
Сейчас работаю в DataGrip, вот картинка пример @MT0
Попробуйте запустить SET SERVEROUTPUT ON;
, чтобы показать вывод консоли перед запуском анонимного блока PL/SQL.
@MT0 Эта команда недействительна в DataGrip, но это не проблема. Мой вывод работает нормально, вы можете видеть на картинке, что он у меня включен. В левом нижнем углу есть иконка с выделенным гамбургер-меню. Когда я оборачиваю немедленную часть выполнения и часть исключения во вложенное начало-конец, все работает нормально
ваш dbms_output является частью исключения, он будет выполнен после нулевой части, которая ничего не делает. У вас есть таблица продаж? если да, то ваше немедленное выполнение не вызовет ошибки, и поэтому dbms_output не будет выполнен.
@gsalem, конечно, вызывает исключение, потому что пункт Into...
отсутствует.
@gsalem Я думаю, ты действительно прав. Это просто пример, это не мой настоящий код. В моем коде есть предложение into, но я думаю, что код рассматривается как часть исключения. Все внутри исключения и конца; рассматривается как часть кода исключения.
@wemfried, нет, исключение не возникает, если нет предложения into. прокомментируйте строку исключения в dbfiddle и попробуйте (после замены продаж на двойные)
@gsalem что для меня странно, так это то, что если я изменю приведенный выше код, чтобы получить исключение, например, no_data_found, мой код действительно запустится. Таким образом, приведенный выше код ничего не выводит, если исключение не вызвано, а если исключение возбуждено, оно выводит 123. Вот почему я не понимаю, как это на самом деле работает. исключение не возбуждается и исключение возбуждается. Разве это не опровергает вашу теорию? Вот что мне показалось очень странным.
Фрэн, все, что находится между «исключениями» и «концом», является частью кода исключения. Если вы хотите что-то сделать после этого, вам понадобятся два блока кода.
@gsalem Да, теперь я это понимаю. Спасибо за помощь!
Здесь важны несколько вещей — синтаксический анализ и выполнение.
Если таблица не существует, то оператор не может быть проанализирован, и, следовательно, мы немедленно получим исключение.
SQL> begin
2 execute immediate 'select * from xxxx';
3 end;
4 /
begin
*
ERROR at line 1:
ORA-00942: table or view does not exist
ORA-06512: at line 2
Однако, если таблица ДЕЙСТВИТЕЛЬНО существует, синтаксический анализ будет в порядке. Поскольку вы никогда не указывали INTO, это все, что мы делаем. Нам никогда не нужно было выполнять и начинать фазу выборки, поэтому ошибок не возникало. Простой способ увидеть, что мы никогда не выполняли оператор, это что-то вроде
SQL> begin
2 execute immediate 'select 1/count(*) from dual where 1=2';
3 end;
4 /
PL/SQL procedure successfully completed.
Если бы мы выполнили, то мы ожидали бы, что выйдет ошибка деления на ноль. В тот момент, когда мы увидим INTO, нам нужно будет выполнить выборку (что потребует выполнения).
Я понимаю это, но приведенный выше код - это просто пример, в моем реальном коде я работаю. Пожалуйста, посмотрите на мой последний комментарий выше в комментариях к исходному вопросу, где я объяснил, что я нашел очень странным. По крайней мере мне.
ваше единственное доказательство того, что вы работаете или нет, - это вывод dbms_output.put_line. Но вот основное, что вы должны понимать. dbms_output.put_line записывает не в консоль, а во внутренний буфер. Затем, по завершении процедуры, вызывающий клиент может (или не может) выбрать, что делать с этим буфером. Некоторые клиенты всегда игнорируют это. sqlplus обработает и отобразит его тогда и только тогда, когда вы ввели команду set serverout on.
@EdStevens Я понимаю, ты прав. Но как один и тот же код может работать, когда возникает исключение, а не когда исключение не возникает? Итак, когда возникает исключение, DataGrip отображает внутренний буфер, а когда исключение не возникает, он его игнорирует?
почему код не выполняется после части исключения, хотя исключение не возникает?
Причина очень проста - dbms_output.put_line
в вопросе нет "после исключения".
Код с правильным отступом эквивалентен:
begin
execute immediate 'select * from dual';
exception when others then
null;
dbms_output.put_line(123);
end;
/
Блок исключения — это все, что находится между EXCEPTIONS
и END;
, и оно будет выполнено, если возникнет исключение.
Невозможно выполнить репликацию, так как возникает исключение. дб<>рабочий пример