“;如何修复oracle pl/sql中的触发器?

“;如何修复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

问题: 需要表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”)无法正确计数到其指定的计数字段中。不知道哪里出了问题

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”。这通常发生在只包含