如何在oracle中插入触发器之前更改table的旧数据?
How to change old data of table with before insert trigger in oracle?
如果新行插入到 table,如果重复行已经存在,我想将两行合并为一个
table TEST ( ID column defined as primary key)
ID ITEM QUANTITY
-- ---- --------
1 KA1 5
2 KA2 2
如果新行插入到 table test 中,值为 (KA1,6),因为项 KA1 已经存在应插入总数量为 11 的新行,应删除旧行。
结果集应该如下:
ID ITEM QUANTITY
-- ---- --------
2 KA2 2
3 KA1 11
其中使用的触发器和内联过程是:
CREATE OR REPLACE TRIGGER MERG_DUP
BEFORE INSERT ON TEST
FOR EACH ROW
BEGIN
FOR VAL IN(SELECT ID,ITEM,QUANTITY, FROM TEST)
LOOP
IF VAL.ITEM=:NEW.ITEM THEN
:NEW.QUANTITY:=:NEW.QUANTITY+VAL.QUANTITY;
XXI_MULTI_PR_REMOVE(VAL.ID);
EXIT;
END IF;
END LOOP;
end;
/
CREATE OR REPLACE PROCEDURE XXI_MULTI_PR_REMOVE(ID number)
IS
PRAGMA AUTONOMOUS_TRANSACTION;
L_TID NUMBER;
BEGIN
L_TID:=ID;
DELETE FROM TEST WHERE ID=L_TID;
commit;
END;
/
您不需要使用 PRAGMA AUTONOMOUS_TRANSACTION
,也不要在您的程序中内联使用 COMMIT
。
对于您的情况,最好将 CREATE TABLE test
与 ID
列定义为 number generated always as identity primary key
.
因此,可以使用以下顺序的语句:
SQL> CREATE TABLE test(
id number generated always as identity primary key,
item varchar2(100),
quantity int
);
/
SQL> INSERT INTO test(item,quantity) VALUES ('KA1',5);
SQL> INSERT INTO test(item,quantity) VALUES ('KA2',2);
SQL> CREATE OR REPLACE PROCEDURE XXI_MULTI_PR_REMOVE( I_ITEM varchar2 ) IS
BEGIN
DELETE TEST WHERE ITEM = I_ITEM;
END;
/
SQL> CREATE OR REPLACE TRIGGER MERG_DUP
BEFORE INSERT ON TEST
FOR EACH ROW
DECLARE
v_qty NUMBER;
BEGIN
BEGIN
SELECT SUM(NVL(QUANTITY,0)) INTO v_qty FROM TEST WHERE ITEM = :NEW.ITEM;
EXCEPTION WHEN OTHERS THEN v_qty := NULL;
END;
IF ( v_qty IS NOT NULL ) THEN
XXI_MULTI_PR_REMOVE(:NEW.ITEM);
:NEW.QUANTITY:=:NEW.QUANTITY+v_qty;
END IF;
END MERG_DUP;
/
SQL> INSERT INTO test(item,quantity) VALUES ('KA3',6);
SQL> COMMIT;
SQL> SELECT * FROM test;
如果新行插入到 table,如果重复行已经存在,我想将两行合并为一个
table TEST ( ID column defined as primary key)
ID ITEM QUANTITY -- ---- -------- 1 KA1 5 2 KA2 2
如果新行插入到 table test 中,值为 (KA1,6),因为项 KA1 已经存在应插入总数量为 11 的新行,应删除旧行。
结果集应该如下:
ID ITEM QUANTITY -- ---- -------- 2 KA2 2 3 KA1 11
其中使用的触发器和内联过程是:
CREATE OR REPLACE TRIGGER MERG_DUP
BEFORE INSERT ON TEST
FOR EACH ROW
BEGIN
FOR VAL IN(SELECT ID,ITEM,QUANTITY, FROM TEST)
LOOP
IF VAL.ITEM=:NEW.ITEM THEN
:NEW.QUANTITY:=:NEW.QUANTITY+VAL.QUANTITY;
XXI_MULTI_PR_REMOVE(VAL.ID);
EXIT;
END IF;
END LOOP;
end;
/
CREATE OR REPLACE PROCEDURE XXI_MULTI_PR_REMOVE(ID number)
IS
PRAGMA AUTONOMOUS_TRANSACTION;
L_TID NUMBER;
BEGIN
L_TID:=ID;
DELETE FROM TEST WHERE ID=L_TID;
commit;
END;
/
您不需要使用 PRAGMA AUTONOMOUS_TRANSACTION
,也不要在您的程序中内联使用 COMMIT
。
对于您的情况,最好将 CREATE TABLE test
与 ID
列定义为 number generated always as identity primary key
.
因此,可以使用以下顺序的语句:
SQL> CREATE TABLE test(
id number generated always as identity primary key,
item varchar2(100),
quantity int
);
/
SQL> INSERT INTO test(item,quantity) VALUES ('KA1',5);
SQL> INSERT INTO test(item,quantity) VALUES ('KA2',2);
SQL> CREATE OR REPLACE PROCEDURE XXI_MULTI_PR_REMOVE( I_ITEM varchar2 ) IS
BEGIN
DELETE TEST WHERE ITEM = I_ITEM;
END;
/
SQL> CREATE OR REPLACE TRIGGER MERG_DUP
BEFORE INSERT ON TEST
FOR EACH ROW
DECLARE
v_qty NUMBER;
BEGIN
BEGIN
SELECT SUM(NVL(QUANTITY,0)) INTO v_qty FROM TEST WHERE ITEM = :NEW.ITEM;
EXCEPTION WHEN OTHERS THEN v_qty := NULL;
END;
IF ( v_qty IS NOT NULL ) THEN
XXI_MULTI_PR_REMOVE(:NEW.ITEM);
:NEW.QUANTITY:=:NEW.QUANTITY+v_qty;
END IF;
END MERG_DUP;
/
SQL> INSERT INTO test(item,quantity) VALUES ('KA3',6);
SQL> COMMIT;
SQL> SELECT * FROM test;