这里是一个布尔表达式,做的伎俩:(PLSQL)在Oracle更新触发器中测试更改值的最简单表达式是什么?
nvl(:new.location != :old.location, (:new.location is null) != (:old.location is null))
但我想认为有一个更简单的表达。有任何想法吗?
这里是一个布尔表达式,做的伎俩:(PLSQL)在Oracle更新触发器中测试更改值的最简单表达式是什么?
nvl(:new.location != :old.location, (:new.location is null) != (:old.location is null))
但我想认为有一个更简单的表达。有任何想法吗?
decode(:old.location, :new.location, 1) is null
编辑:它可能更清楚地说:
decode(:old.location, :new.location, null, 1) = 1
您可以创建这样一个重载包功能:
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)。
这些较短的方法都有一些缺点。 它们是缓慢的,不直观的,潜在的错误(尽可能避免魔术值), 以及比正常条件更专有的,比如AND/OR/IS NULL/IS NOT NULL。
NVL,DECODE,COALESCE等可能比您想象的要贵。
我已经看到了这个,很多时候在几个不同的情况下,这里有一个简单的例子:
--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;
/
我建议你花额外的第二输入它的逻辑方式。你的代码看起来更好,运行速度更快。
我不知道为什么,但在我们的环境11g R1中却是相反的。第一个nvl解决方案花费0,125秒,第二个解决方案花费0,235秒。如果我注释掉“j:= 1”,那么它们大约快0.05秒。 – 2010-10-29 08:06:20
也许你只想触发器在所有值都发生改变时触发?如果是这样,创建触发器时最好使用以下语法:
CREATE OR REPLACE TRIGGER DepartTrigger BEFORE UPDATE OF location ON Department
...尽管您仍然需要检查更改,因为“更新部门集合位置=位置”会触发该触发器。 – 2010-09-10 08:37:16
我喜欢第一个版本的简单性。不幸的是,它的作用并不是很明显,但有了足够的使用,我想它可能会变得习惯。它很简单,很容易被识别。 – rattigan 2010-10-21 20:31:48