Почему код в PLSQL не выполняется после части «исключения»?

Поэтому я сделал ошибку, из-за которой я не помещал немедленное выполнение во вложенный блок начала-конца, поэтому мой код не работал. Так что в основном у меня было

begin
 execute immediate 'select * from sales';
 exception when others then null;
 dbms_output.put_line(123);
end;

Dbms_output не напечатал «123», и я понял, что мне нужно поместить немедленное выполнение в начало-конец. Я хочу быть уверен, поэтому мой вопрос: почему код не выполняется после части исключения, даже если исключение не возникает?

Невозможно выполнить репликацию, так как возникает исключение. дб<>рабочий пример

MT0 26.12.2020 17:41

Сейчас работаю в DataGrip, вот картинка пример @MT0

Fran Turkovic 26.12.2020 17:45

Попробуйте запустить SET SERVEROUTPUT ON;, чтобы показать вывод консоли перед запуском анонимного блока PL/SQL.

MT0 26.12.2020 17:46

@MT0 Эта команда недействительна в DataGrip, но это не проблема. Мой вывод работает нормально, вы можете видеть на картинке, что он у меня включен. В левом нижнем углу есть иконка с выделенным гамбургер-меню. Когда я оборачиваю немедленную часть выполнения и часть исключения во вложенное начало-конец, все работает нормально

Fran Turkovic 26.12.2020 18:09

ваш dbms_output является частью исключения, он будет выполнен после нулевой части, которая ничего не делает. У вас есть таблица продаж? если да, то ваше немедленное выполнение не вызовет ошибки, и поэтому dbms_output не будет выполнен.

gsalem 26.12.2020 19:13

@gsalem, конечно, вызывает исключение, потому что пункт Into... отсутствует.

Wernfried Domscheit 26.12.2020 19:24

@gsalem Я думаю, ты действительно прав. Это просто пример, это не мой настоящий код. В моем коде есть предложение into, но я думаю, что код рассматривается как часть исключения. Все внутри исключения и конца; рассматривается как часть кода исключения.

Fran Turkovic 26.12.2020 19:48

@wemfried, нет, исключение не возникает, если нет предложения into. прокомментируйте строку исключения в dbfiddle и попробуйте (после замены продаж на двойные)

gsalem 26.12.2020 20:14

@gsalem что для меня странно, так это то, что если я изменю приведенный выше код, чтобы получить исключение, например, no_data_found, мой код действительно запустится. Таким образом, приведенный выше код ничего не выводит, если исключение не вызвано, а если исключение возбуждено, оно выводит 123. Вот почему я не понимаю, как это на самом деле работает. исключение не возбуждается и исключение возбуждается. Разве это не опровергает вашу теорию? Вот что мне показалось очень странным.

Fran Turkovic 27.12.2020 02:07

Фрэн, все, что находится между «исключениями» и «концом», является частью кода исключения. Если вы хотите что-то сделать после этого, вам понадобятся два блока кода.

gsalem 28.12.2020 13:08

@gsalem Да, теперь я это понимаю. Спасибо за помощь!

Fran Turkovic 28.12.2020 23:16
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
11
590
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Здесь важны несколько вещей — синтаксический анализ и выполнение.

Если таблица не существует, то оператор не может быть проанализирован, и, следовательно, мы немедленно получим исключение.

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, нам нужно будет выполнить выборку (что потребует выполнения).

Я понимаю это, но приведенный выше код - это просто пример, в моем реальном коде я работаю. Пожалуйста, посмотрите на мой последний комментарий выше в комментариях к исходному вопросу, где я объяснил, что я нашел очень странным. По крайней мере мне.

Fran Turkovic 27.12.2020 15:42

ваше единственное доказательство того, что вы работаете или нет, - это вывод dbms_output.put_line. Но вот основное, что вы должны понимать. dbms_output.put_line записывает не в консоль, а во внутренний буфер. Затем, по завершении процедуры, вызывающий клиент может (или не может) выбрать, что делать с этим буфером. Некоторые клиенты всегда игнорируют это. sqlplus обработает и отобразит его тогда и только тогда, когда вы ввели команду set serverout on.

EdStevens 27.12.2020 17:21

@EdStevens Я понимаю, ты прав. Но как один и тот же код может работать, когда возникает исключение, а не когда исключение не возникает? Итак, когда возникает исключение, DataGrip отображает внутренний буфер, а когда исключение не возникает, он его игнорирует?

Fran Turkovic 27.12.2020 23:28
Ответ принят как подходящий

почему код не выполняется после части исключения, хотя исключение не возникает?

Причина очень проста - dbms_output.put_line в вопросе нет "после исключения".

Код с правильным отступом эквивалентен:

begin
    execute immediate 'select * from dual';
exception when others then 
    null;
    dbms_output.put_line(123);
end;
/

Блок исключения — это все, что находится между EXCEPTIONS и END;, и оно будет выполнено, если возникнет исключение.

Другие вопросы по теме