Семантика хранимых процедур / функций Oracle в контексте транзакций - PullRequest
2 голосов
/ 28 июля 2011

Недавно у меня был какой-то вклад коллеги относительно фиксации в сохраненной функции.Используем ли мы процедуры или функции для выполнения автономной / пакетной логики в базе данных Oracle, в большинстве случаев дело нашего вкуса.В обоих случаях мы возвращаем код либо как результат функции, либо как параметр процедуры OUT.Обычно мы требуем, чтобы эти автономные / пакетные подпрограммы вызывались из PL / SQL, а не из SQL:

-- good
declare
  rc number(7);
begin
  rc := our_function(1, 2, 3);
end;

-- less good
select our_function(1, 2, 3) from dual;

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

Вопрос в следующем: существуют ли передовые практики по этой теме или какие-то специальные ключевые слова, которые не позволяют использовать такие функции в инструкциях SQL на уровне компилятора?Или мы должны избегать функций для пакетных операций и использовать только процедуры?

Ответы [ 3 ]

6 голосов
/ 28 июля 2011

Вы можете использовать RESTRICT_REFERENCES , чтобы указать, что функция не будет читать / записывать пакет или состояние базы данных.

CREATE PACKAGE t_pkg AS
   FUNCTION showup (msg VARCHAR2) RETURN VARCHAR2;
   PRAGMA RESTRICT_REFERENCES(showup, WNDS, RNDS);
END t_pkg;
/
-- create the package body
CREATE OR REPLACE PACKAGE BODY t_pkg AS
   FUNCTION showup (msg VARCHAR2) RETURN VARCHAR2 IS
    v_val varchar2(1);
   BEGIN
      select dummy into v_val from dual;
      RETURN v_val;
   END;
END t_pkg;
/

Раньше был случай, когда SQL не позволял бы вам вызывать функцию, если он не дал такого обещания, но это ограничение было снято.

Я бы предпочел сделать это разграничением между процедурой и функцией. Следует иметь в виду, что если функция PL / SQL вызывает исключение NO_DATA_FOUND, вызывающий оператор SQL не завершается ошибкой (поскольку никакие данные не являются ошибкой SQL). Поэтому я предпочитаю использовать процедуры, если объект специально не предназначен для вызова из SQL.

2 голосов
/ 28 июля 2011

Есть ли передовые практики по этой теме, или какие-то специальные ключевые слова , которые запрещают использование таких функций в инструкциях SQL на уровне компилятора?

Если вы используете функцию, которая требует транзакции (и, следовательно, фиксации), AFAIK вы не сможете вызвать ее из SELECT, если функция не использует АВТОНОМНУЮ СДЕЛКУ (в противном случае вы получаете ORA-14551 cannot perform a DML operation inside a query).

См. Также: ORA-14551: невозможно выполнить операцию DML внутри запроса

Таким образом, наличие функции, которая требует самой транзакции, должно предотвращать ее вызов из SELECT.

1 голос
/ 28 июля 2011

С моей точки зрения, нет способа сделать это. Хотя вы можете избежать ошибок времени выполнения, таких как "ORA-14551", используя PRAGMA RESTRICT_REFERENCES в "our_function (1, 2, 3)", чтобы быть уверенным, что это безопасноиспользовать его SQL-запрос, но вы не можете запретить его использование в SQL на уровне компилятора

...