(PLSQL)在Oracle on update触发器中测试更改值的最简单表达式是什么?

(PLSQL)在Oracle on update触发器中测试更改值的最简单表达式是什么?,oracle,plsql,triggers,Oracle,Plsql,Triggers,下面是一个布尔表达式,它实现了以下功能: nvl(:new.location != :old.location, (:new.location is null) != (:old.location is null)) 但我想有一个更简单的表达。有什么想法吗?您可以创建一个重载包函数,如下所示: package p is function changed (p_old varchar2, p_new varchar2) return voolean; function chan

下面是一个布尔表达式,它实现了以下功能:

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

但我想有一个更简单的表达。有什么想法吗?

您可以创建一个重载包函数,如下所示:

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)

编辑:可以更清楚地说:

decode(:old.location, :new.location, null, 1) = 1

这些较短的方法都有几个缺点。 它们速度慢,不直观,可能有缺陷(尽可能避免使用魔法值), 并且比正常条件更专有,如和/或/为空/不为空

NVL、解码、合并等,可能比您想象的更昂贵

我在不同的环境中多次看到这一点,下面是一个简单的例子:

--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;
/
--更短的方法:大约需要0.45秒
声明
j数;
开始
因为我在1。。1000000循环
j:=i;
如果nvl(i j,(i为空)(j为空))则
无效的
如果结束;
端环;
结束;
/
--正常方法:大约需要0.25秒
声明
j数;
开始
因为我在1。。1000000循环
j:=i;
如果i j或(i为null且j不为null)或(i为null且j为null),则
无效的
如果结束;
端环;
结束;
/

我建议您多花一秒钟,以合乎逻辑的方式键入它。您的代码将看起来更好,运行更快。

也许您只希望在值发生更改时触发触发器?如果是这样,最好在创建触发器时使用以下语法:

CREATE OR REPLACE TRIGGER DepartTrigger BEFORE UPDATE OF location ON Department

... 尽管您仍然需要检查更改,因为“update department set location=location”将触发触发器。我喜欢您的第一个版本的简单性。不幸的是,它的作用不是很明显,但如果使用足够多,我想它可能会变成习惯用语。它很简单,很容易被识别。我不知道为什么,但在我们的环境11GR1中,它是相反的。第一个nvl解决方案平均耗时0125秒,第二个解决方案耗时0235秒。如果我把“j:=1”注释掉,那么两者都快了0,05秒。
CREATE OR REPLACE TRIGGER DepartTrigger BEFORE UPDATE OF location ON Department