Необходим ли коммит после операции DML в функции / процедуре?

20

Интересно узнать, нужно ли писать коммит после вставки / удаления / обновления в функции / процедуре?

Пример:

create or replace function test_fun
return number is
begin
   delete from a;
   return 0;
end;

или процедура

create or replace procedure aud_clear_pro
as
begin
   delete from a;
end;

нужно ли фиксировать после удаления?

Не могу понять следующую ситуацию:

  1. Если я вызываю функцию / процедуру из окна SQL, тогда требуется фиксация

    но

  2. Если я планирую функцию / процедуру с использованием dbms_scheduler и запускаю задание, оператор удаления автоматически фиксируется.

    ПОЧЕМУ?

купа
источник

Ответы:

24

В общем, процедуры не должны совершать. Эти виды решений по управлению транзакциями следует оставить для кода более высокого уровня, который знает, когда логическая транзакция фактически завершена. Если вы фиксируете внутри хранимой процедуры, вы ограничиваете ее повторное использование, потому что вызывающая сторона, которая хочет, чтобы изменения, вносимые процедурой, были частью более крупной транзакции, не могла просто вызвать процедуру напрямую.

Если вы вызываете процедуру в интерактивном режиме, вам придется явно зафиксировать или откатить транзакцию, потому что Oracle не знает, намерены ли вы вызывать процедуру как логическую транзакцию или если вы намереваетесь составить более крупную транзакцию, включающую несколько вызовов процедур. Если вы используете dbms_scheduler, dbms_schedulerпредполагается, что задание является логической транзакцией, и фиксирует в конце задания, предполагая, что оно выполнено успешно ( dbms_jobделает то же самое).

Функции не должны манипулировать данными в первую очередь. Функция, которая манипулирует данными, не может быть вызвана из оператора SQL (за исключением случая, когда сама функция объявляет использование автономной транзакции, которая почти никогда не подходит). Весь смысл наличия как функций, так и процедур заключается в том, что функции могут быть встроены в операторы SQL и могут более свободно предоставляться пользователям, поскольку они не изменяют никаких данных.

Джастин Кейв
источник
1
Разве в Oracle не возможно, чтобы вызывающая сторона начала транзакцию, которая связывает вызовы процедур? В SQL Server вы можете зафиксировать внутри процедуры, но если вызывающая сторона открыла транзакцию до вызова этой процедуры, ничего не будет зафиксировано, пока вызывающая сторона тоже не подтвердит фиксацию.
Ник Чаммас
4
@NickChammas - у Oracle нет концепции вложенной транзакции, нет. Если процедура фиксируется, то все, что сделал вызывающий до этого момента, будет зафиксировано. Вызывающая сторона всегда запускает транзакцию неявно с ее первой инструкции (будь то вызов процедуры или что-то еще), поэтому она всегда должна быть до вызывающей стороны, чтобы завершить транзакцию.
Джастин Кейв
@JustinCave Хотя это правда, не забывайте об автономных транзакциях.
Philᵀᴹ
@Phil - Да, но это совсем другое животное. Автономная транзакция не может видеть незавершенные изменения, внесенные вызывающей стороной, и не может быть отменена вызывающей стороной, поэтому крайне маловероятно, что что-либо, кроме процедуры ведения журнала, должно быть объявлено для использования автономной транзакции.
Джастин Кейв
4

Ответить на ваш вопрос; ПОЧЕМУ?

Вы, наверное, уже знаете это, поскольку посту уже 2 года. Но я отвечу только для записи.

Причина, по которой № 1 требует фиксации, а № 2 - нет, заключается в том, что настройка базы данных по умолчанию в Oracle заключается в фиксации транзакции по окончании сеанса. Если вы находитесь в sqlplus и запускаете свой код вручную, он не сразу завершит транзакцию. Если вы выполните явную фиксацию или вы выйдете из sqlpus, транзакция будет зафиксирована.

Причина, по которой вы получаете автоматический коммит на # 2, заключается в том, что он создает сеанс для запуска вашего скрипта. Когда он завершается, он автоматически выходит из системы, что приводит к автоматической фиксации.

Стив Каннингем
источник