“;如何修复oracle pl/sql中的触发器?
问题: 需要表a的触发器,该表执行以下操作: 每次在TRT_程序值列的表A中插入时,添加1 到表B中的“TRT\U INS\U COUNT”列。如果TRT\U程序值 表B中不存在,请在表B中添加一行以进行程序设置 TRT_in_计数为1 每次对表a进行删除时,在中的TRT_DEL_COUNT列中添加1 如果程序值存在于表B中,请参见表B。如果不存在,请参见表B 存在于表B中,在表B中为程序添加一行并设置 TRT_DEL_计数为1 每次更新表A中的TRT_列过程时,将1添加到 表B中的TRT\U UPD\U COUNT列。如果不在表B中,请在 表B显示程序值,并将TRT_UPD_COUNT设置为1。如果列 表A中的TRT_程序值已更改,将1添加到该程序的TRT_UPD_计数中 旧程序值 通过多次插入、删除和更新进行测试,然后显示表B 更新:每当trt_程序的值插入表B中时,第二个相同的trt_程序(例如“88-20”)无法正确计数到其指定的计数字段中。不知道哪里出了问题“;如何修复oracle pl/sql中的触发器?,oracle,plsql,database-trigger,Oracle,Plsql,Database Trigger,问题: 需要表a的触发器,该表执行以下操作: 每次在TRT_程序值列的表A中插入时,添加1 到表B中的“TRT\U INS\U COUNT”列。如果TRT\U程序值 表B中不存在,请在表B中添加一行以进行程序设置 TRT_in_计数为1 每次对表a进行删除时,在中的TRT_DEL_COUNT列中添加1 如果程序值存在于表B中,请参见表B。如果不存在,请参见表B 存在于表B中,在表B中为程序添加一行并设置 TRT_DEL_计数为1 每次更新表A中的TRT_列过程时,将1添加到 表B中的TRT\U
TABLE A
Name Null Type
TRT_ID NOT NULL NUMBER(3)
PAT_NBR NUMBER(4)
PHYS_ID NUMBER(3)
TRT_PROCEDURE VARCHAR2(5)
TRT_DATE DATE
TABLE B
Name Null Type
TRT_PROCEDURE NOT NULL VARCHAR2(5)
TRT_INS_COUNT NUMBER(3)
TRT_DEL_COUNT NUMBER(3)
TRT_UPD_COUNT NUMBER(3)
TEST SAMPLES
INSERT INTO A VALUES (11, 8031,101,'88-20',sysdate );
INSERT INTO A VALUES (12, 5872,101,'60-00',sysdate );
UPDATE A SET trt_procedure = '88-20' WHERE trt_id=6;
/*row trt_id =6 cloumn trt_procedure old value '54-60'
new value '88-20', which means Table B row '88-20' and
row '54-60 both trt_upd_count should add 1*/
DELETE FROM A WHERE trt_id=1;
/*row trt_id =1 cloumn trt_procedure value also '88-20', which means
that Table B row '88-20' trt_del_count should also add 1*/
CREATE OR REPLACE TRIGGER trt_stats_trg
BEFORE INSERT OR UPDATE OR DELETE OF TRT_procedure ON A FOR EACH ROW
BEGIN
IF INSERTING THEN
UPDATE B SET trt_ins_count = trt_ins_count+1
WHERE B.trt_procedure = :new.trt_procedure;
IF SQL%NOTFOUND THEN
INSERT INTO B (trt_procedure, trt_ins_count)
VALUES (:new.trt_procedure, 1);
END IF;
ELSIF UPDATING THEN
UPDATE B SET trt_upd_count = trt_upd_count+1
WHERE B.trt_procedure = :old.trt_procedure;
IF SQL%NOTFOUND THEN
INSERT INTO B (trt_procedure, trt_upd_count)
VALUES (:old.trt_procedure, 1);
END IF;
UPDATE B SET trt_upd_count = trt_upd_count+1
WHERE B.trt_procedure = :new.trt_procedure;
IF SQL%NOTFOUND THEN
INSERT INTO B (trt_procedure, trt_upd_count)
VALUES (:new.trt_procedure, 1);
END IF;
ELSIF DELETING THEN
UPDATE B SET trt_del_count = trt_del_count+1
WHERE B.trt_procedure = :old.trt_procedure;
IF SQL%NOTFOUND THEN
INSERT INTO B (trt_procedure, trt_del_count)
VALUES (:old.trt_procedure, 1);
END IF;
END IF;
END trt_stats_trg;
在触发器的
如果插入部分
UPDATE B
SET trt_ins_count = trt_ins_count+1
WHERE :old.trt_procedure = :new.trt_procedure;
插入新行时,:OLD
伪行中的所有值都为空,因此您的更新将永远不会更新任何内容。我想你是说
UPDATE B
SET trt_ins_count = trt_ins_count+1
WHERE B.trt_procedure = :new.trt_procedure;
尝试一下,看看这是否有助于解决您的问题。如果插入触发器的部分
UPDATE B
SET trt_ins_count = trt_ins_count+1
WHERE :old.trt_procedure = :new.trt_procedure;
插入新行时,:OLD
伪行中的所有值都为空,因此您的更新将永远不会更新任何内容。我想你是说
UPDATE B
SET trt_ins_count = trt_ins_count+1
WHERE B.trt_procedure = :new.trt_procedure;
尝试一下,看看这是否有助于解决您的问题。给您,还有一些修复
各表:
create table a(
TRT_ID NUMBER(3) NOT NULL ,
PAT_NBR NUMBER(4),
PHYS_ID NUMBER(3),
TRT_PROCEDURE VARCHAR2(5),
TRT_DATE DATE
);
create table b(
TRT_PROCEDURE VARCHAR2(5) NOT NULL,
TRT_INS_COUNT NUMBER(3),
TRT_DEL_COUNT NUMBER(3),
TRT_UPD_COUNT NUMBER(3)
);
扳机呢
CREATE OR REPLACE TRIGGER trt_stats_trg
BEFORE INSERT OR UPDATE OR DELETE ON A FOR EACH ROW
BEGIN
IF INSERTING THEN
UPDATE B SET trt_ins_count = nvl(trt_ins_count,0)+1
WHERE B.trt_procedure = :new.trt_procedure;
IF SQL%NOTFOUND THEN
INSERT INTO B (trt_procedure, trt_ins_count)
VALUES (:new.trt_procedure, 1);
END IF;
ELSIF UPDATING('TRT_PROCEDURE') THEN
if nvl(:old.trt_procedure, 'X') <> nvl(:new.trt_procedure, 'X') then
UPDATE B SET trt_upd_count = nvl(trt_upd_count,0)+1
WHERE B.trt_procedure = :old.trt_procedure;
IF SQL%NOTFOUND THEN
INSERT INTO B (trt_procedure, trt_upd_count)
VALUES (:old.trt_procedure, 1);
END IF;
UPDATE B SET trt_upd_count = nvl(trt_upd_count,0)+1
WHERE B.trt_procedure = :new.trt_procedure;
IF SQL%NOTFOUND THEN
INSERT INTO B (trt_procedure, trt_upd_count)
VALUES (:new.trt_procedure, 1);
END IF;
end if;
ELSIF DELETING THEN
UPDATE B SET trt_del_count = nvl(trt_del_count, 0)+1
WHERE B.trt_procedure = :old.trt_procedure;
IF SQL%NOTFOUND THEN
INSERT INTO B (trt_procedure, trt_del_count)
VALUES (:old.trt_procedure, 1);
END IF;
END IF;
END trt_stats_trg;
/
创建或替换触发器trt\u stats\u trg
在为每行插入、更新或删除之前
开始
如果插入,则
更新B SET trt\U ins\U count=nvl(trt\U ins\U count,0)+1
其中B.trt_程序=:new.trt_程序;
如果找不到SQL%n,则
插入B(trt\U程序、trt\U ins\U计数)
值(:new.trt_程序,1);
如果结束;
ELSIF更新(“TRT_程序”),然后
如果nvl(:old.trt_procedure,'X')nvl(:new.trt_procedure,'X'),则
更新B设置trt\U upd\U计数=nvl(trt\U upd\U计数,0)+1
其中B.trt_程序=:old.trt_程序;
如果找不到SQL%n,则
插入B(trt\U程序、trt\U upd\U计数)
值(:old.trt_程序,1);
如果结束;
更新B设置trt\U upd\U计数=nvl(trt\U upd\U计数,0)+1
其中B.trt_程序=:new.trt_程序;
如果找不到SQL%n,则
插入B(trt\U程序、trt\U upd\U计数)
值(:new.trt_程序,1);
如果结束;
如果结束;
如果删除,则
更新B SET trt\U del\U count=nvl(trt\U del\U count,0)+1
其中B.trt_程序=:old.trt_程序;
如果找不到SQL%n,则
插入B(trt\U程序、trt\U del\U计数)
值(:old.trt_程序,1);
如果结束;
如果结束;
结束训练统计训练;
/
要点:
- 您可以使用
更新('COLUMN_NAME')
来检测SQL何时影响特定列
- 当
更新时
,您可能希望检查未更改的更新,其中值为“ABC”的列将更新为“ABC”。这种情况经常发生在只在更新中包含所有列的框架中,即使它们并没有真正改变。如果nvl(:old.trt_procedure,'X')nvl(:new.trt_procedure,'X'),则使用类似于的方法检测此情况,然后
- 表
B
没有计数的默认值,因此当原始触发器尝试更新表B
时,它成功地…将NULL
更新为NULL
,这是在NULL
中添加1时发生的情况。可以通过为表中的列指定默认值0
,或者使用NVL(trt\u upd\u count,0)+1
而不是trt\u upd\u count+1
来解决此问题
- 最后,注意
:new
和:old
的用法。看起来他们在这个触发器中是正确的,但这将取决于您的商业案例
给你,还有一些修正
各表:
create table a(
TRT_ID NUMBER(3) NOT NULL ,
PAT_NBR NUMBER(4),
PHYS_ID NUMBER(3),
TRT_PROCEDURE VARCHAR2(5),
TRT_DATE DATE
);
create table b(
TRT_PROCEDURE VARCHAR2(5) NOT NULL,
TRT_INS_COUNT NUMBER(3),
TRT_DEL_COUNT NUMBER(3),
TRT_UPD_COUNT NUMBER(3)
);
扳机呢
CREATE OR REPLACE TRIGGER trt_stats_trg
BEFORE INSERT OR UPDATE OR DELETE ON A FOR EACH ROW
BEGIN
IF INSERTING THEN
UPDATE B SET trt_ins_count = nvl(trt_ins_count,0)+1
WHERE B.trt_procedure = :new.trt_procedure;
IF SQL%NOTFOUND THEN
INSERT INTO B (trt_procedure, trt_ins_count)
VALUES (:new.trt_procedure, 1);
END IF;
ELSIF UPDATING('TRT_PROCEDURE') THEN
if nvl(:old.trt_procedure, 'X') <> nvl(:new.trt_procedure, 'X') then
UPDATE B SET trt_upd_count = nvl(trt_upd_count,0)+1
WHERE B.trt_procedure = :old.trt_procedure;
IF SQL%NOTFOUND THEN
INSERT INTO B (trt_procedure, trt_upd_count)
VALUES (:old.trt_procedure, 1);
END IF;
UPDATE B SET trt_upd_count = nvl(trt_upd_count,0)+1
WHERE B.trt_procedure = :new.trt_procedure;
IF SQL%NOTFOUND THEN
INSERT INTO B (trt_procedure, trt_upd_count)
VALUES (:new.trt_procedure, 1);
END IF;
end if;
ELSIF DELETING THEN
UPDATE B SET trt_del_count = nvl(trt_del_count, 0)+1
WHERE B.trt_procedure = :old.trt_procedure;
IF SQL%NOTFOUND THEN
INSERT INTO B (trt_procedure, trt_del_count)
VALUES (:old.trt_procedure, 1);
END IF;
END IF;
END trt_stats_trg;
/
创建或替换触发器trt\u stats\u trg
在为每行插入、更新或删除之前
开始
如果插入,则
更新B SET trt\U ins\U count=nvl(trt\U ins\U count,0)+1
其中B.trt_程序=:new.trt_程序;
如果找不到SQL%n,则
插入B(trt\U程序、trt\U ins\U计数)
值(:new.trt_程序,1);
如果结束;
ELSIF更新(“TRT_程序”),然后
如果nvl(:old.trt_procedure,'X')nvl(:new.trt_procedure,'X'),则
更新B设置trt\U upd\U计数=nvl(trt\U upd\U计数,0)+1
其中B.trt_程序=:old.trt_程序;
如果找不到SQL%n,则
插入B(trt\U程序、trt\U upd\U计数)
值(:old.trt_程序,1);
如果结束;
更新B设置trt\U upd\U计数=nvl(trt\U upd\U计数,0)+1
其中B.trt_程序=:new.trt_程序;
如果找不到SQL%n,则
插入B(trt\U程序、trt\U upd\U计数)
值(:new.trt_程序,1);
如果结束;
如果结束;
如果删除,则
更新B SET trt\U del\U count=nvl(trt\U del\U count,0)+1
其中B.trt_程序=:old.trt_程序;
如果找不到SQL%n,则
插入B(trt\U程序、trt\U del\U计数)
值(:old.trt_程序,1);
如果结束;
如果结束;
结束训练统计训练;
/
要点:
- 您可以使用
更新('COLUMN_NAME')
来检测SQL何时影响特定列
- 当
更新时
,您可能希望检查未更改的更新,其中值为“ABC”的列将更新为“ABC”。这通常发生在只包含