(PLSQL) Какое простейшее выражение для проверки измененного значения в триггере Oracle при обновлении? - PullRequest
3 голосов
/ 09 сентября 2010

Вот логическое выражение, которое делает трюк:

nvl(:new.location != :old.location, (:new.location is null) != (:old.location is null))

Но я хотел бы думать, что было более простое выражение. Есть идеи?

Ответы [ 4 ]

3 голосов
/ 10 сентября 2010

Все эти более короткие методы имеют несколько недостатков.Они медленные, не интуитивно понятные, потенциально ошибочны (избегайте магических значений, когда это возможно) и являются более проприетарными, чем обычные условия, такие как И / ИЛИ / НУЛЯЮТ / НЕ НУЛИ.

быть дороже, чем вы думаете.

Я видел это много раз в нескольких различных контекстах, вот простой пример:

--Shorter method: Takes about 0.45 seconds
declare
  j number;
begin
  for i in 1 .. 1000000 loop
    j := i;
    if nvl(i <> j, (i is null) <> (j is null)) then
      null;
    end if;
  end loop;
end;
/

--Normal method: Takes about 0.25 seconds
declare
  j number;
begin
  for i in 1 .. 1000000 loop
    j := i;
    if i <> j or (i is null and j is not null) or (i is not null and j is null) then
      null;
    end if;
  end loop;
end;
/

Я рекомендую вам потратить лишнюю секунду, чтобы набрать егологичный путь.Ваш код будет выглядеть лучше и работать быстрее.

2 голосов
/ 09 сентября 2010

Вы можете создать перегруженную функцию пакета следующим образом:

package p is

    function changed (p_old varchar2, p_new varchar2) return voolean;
    function changed (p_old number, p_new number) return voolean;
    function changed (p_old date, p_new date) return voolean;

end;

Тогда просто позвоните в триггеры:

if p.changed(:old.location,:new.location) then ...

В качестве альтернативы вы можете просто сделать это:

if nvl(:old.location,'£$%') != nvl(:new.location,'£$%') then ...

Конечно, вы должны выбрать значение, которое никогда не может быть реальным местоположением, что может быть сложно в некоторых случаях. Для VARCHAR2 вы можете выбрать значение, которое слишком велико для размера столбца (если это не 4000).

1 голос
/ 09 сентября 2010
decode(:old.location, :new.location, 1) is null

edit: Возможно, будет более понятно сказать:

decode(:old.location, :new.location, null, 1) = 1
0 голосов
/ 10 сентября 2010

Возможно, вы хотите, чтобы триггер срабатывал только при изменении значения? Если это так, то лучше всего использовать этот синтаксис при создании триггера:

CREATE OR REPLACE TRIGGER DepartTrigger BEFORE UPDATE OF location ON Department
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...