【发布时间】:2021-10-16 10:24:21
【问题描述】:
我是触发器的新手,在更新触发器期间遇到问题。 设想: 我有两个表 [table1 和 table2] 当 table1 中的特定列发生变化时,我需要根据几个条件更新 table2 记录
这是我的触发器,
create or replace TRIGGER UPDATE_TABLE1
BEFORE UPDATE OF LOWTHRESHOLD, HIGHTHRESHOLD ON TABLE1
for each row
when(nvl(old.LOWTHRESHOLD,0) <> nvl(new.LOWTHRESHOLD,0)
OR nvl(old.HIGHTHRESHOLD,0) <> nvl(new.HIGHTHRESHOLD,0))
declare
PID number(3) := nvl(:old.PID,0);
oldLOWTH number(2) := nvl(:old.LOWTHRESHOLD,0);
oldHIGHTH number(2) := nvl(:old.HIGHTHRESHOLD,0);
newLOWTH number(2) := nvl(:new.LOWTHRESHOLD,0);
newHIGHTH number(2) := nvl(:new.HIGHTHRESHOLD,0);
ratio DOUBLE PRECISION;
oldTHCrossed number(1) := 0;
objID number(10) := 0;
objType number(1) := 0;
CURSOR profileUtil_Cursor IS
SELECT * FROM TABLE2 where upid = PID;
begin
dbms_output.enable(1000);
FOR v_record in profileUtil_Cursor LOOP
ratio := v_record.UTILIZATIONRATIO;
oldTHCrossed := v_record.THCROSSED;
objID := v_record.objID;
objType := v_record.objType;
IF(ratio < newLOWTH AND ratio < newHIGHTH ) THEN
UPDATE TABLE2 SET THCROSSED = 1, LASTUPDATED = date_to_miniseconds(sysdate)
WHERE objID = objID and objType = objType and upid = PID;
ELSIF(newLOWTH <= ratio AND ratio <= newHIGHTH) THEN
UPDATE TABLE2 SET THCROSSED = 2, LASTUPDATED = date_to_miniseconds(sysdate)
WHERE objID = objID and objType = objType and upid = PID;
ELSIF(ratio > newHIGHTH) THEN
UPDATE TABLE2 SET THCROSSED = 3, LASTUPDATED = date_to_miniseconds(sysdate)
WHERE upid = PID and objID = objID and objType = objType;
END IF;
END LOOP;
IF SQL%NOTFOUND THEN
DBMS_OUTPUT.put_line('NOT FOUND');
END IF;
END;
但是当这个触发器被执行时,TABLE2 中的所有记录都被更新了。 请提供一些解决此问题的建议。
【问题讨论】:
-
不要使用与列名相同的变量名。因为那时您无法分辨什么是变量,什么是表列。目前我可以假设
WHERE objID = objID and objType = objType是常量,除非某些列具有null值。除上述问题外,您还可以使用merge语句和case表达式计算THCROSSED来更新目标表,无需命令逻辑。 -
看起来这三个更新除了
thcrossed的值是一样的。我会将其作为变量,根据您的逻辑将其设置为 1、2 或 3,然后进行一次更新。此外,稍微小心地格式化代码可以更轻松地处理和发现问题。 -
另外,
IF SQL%NOTFOUND永远不会为真,因为唯一的 SQL 是游标 FOR 循环的一部分。 -
问题是因为变量名称与@astentx 突出显示的列名称相同。修正后,更新正常。
标签: oracle plsql triggers sql-update