很久没有更新博客了,最近比较忙在学反爬和做客制化键盘线,有感兴趣的老哥可以一起交流下
前几天有个老哥,找我帮忙处理数据库问题,需求定时删除特定的数据,我说可以用oracle的定时计划,实际了解到需求之后才知道原来是想要在数据库进入表之前就把数据删除。
我这边首先想到是用触发器来实现,因为触发器里面是可以执行存储过程的。删除的操作我们用存储过程来实现就可以了。
CREATE TABLE C_DPRECODE_C(
CAR_NUM VARCHAR2(20)
);
CREATE TABLE C_DPRECODE(
CAR_NUM VARCHAR(20),
CAP_DATE VARCHAR(30)
);
INSERT INTO C_DPRECODE_C
(CAR_NUM)
SELECT LEVEL FROM DUAL CONNECT BY ROWNUM <= 3;
COMMIT;
首先我们创建存储过程
CREATE OR REPLACE PROCEDURE DELETE_DPRECODE IS
BEGIN
DELETE C_DPRECODE
WHERE CAR_NUM IN (SELECT CAR_NUM FROM C_DPRECODE_C);
COMMIT;
END;
触发器
CREATE OR REPLACE TRIGGER TEST_C_DPRECODE
AFTER INSERT ON C_DPRECODE
FOR EACH ROW
DECLARE
NEXTID NUMBER;
BEGIN
SELECT COUNT(1)
INTO NEXTID
FROM C_DPRECODE
WHERE CAR_NUM IN (SELECT CAR_NUM FROM C_DPRECODE_C);
IF NEXTID > 1
THEN
--删除数据
DELETE_DPRECODE;
END IF;
END;
我们执行插入语句
INSERT INTO C_DPRECODE(CAR_NUM, CAP_DATE)
SELECT LEVEL,
SYSDATE
FROM DUAL
CONNECT BY ROWNUM <= 10;
COMMIT;
报错ORA-04091:表XXXX发生了变化,触发器函数不能读它
报错原因是:
我们建触发器时创建的是行级触发器,我们插入每一行时都会触发这个触发器,导致报错,我们实际需求也不需要每行读,每次操作读一次就可以,于是修改触发器,删除第三行的FOR EACH ROW
CREATE OR REPLACE TRIGGER TEST_C_DPRECODE
AFTER INSERT ON C_DPRECODE
DECLARE
NEXTID NUMBER;
BEGIN
SELECT COUNT(1)
INTO NEXTID
FROM C_DPRECODE
WHERE CAR_NUM IN (SELECT CAR_NUM FROM C_DPRECODE_C);
IF NEXTID > 1
THEN
--删除数据
DELETE_DPRECODE;
END IF;
END;
执行再次报错ORA-04092:COMMIT 不能再触发器中
这次报错的内容为commit不能在触发器中,原因是我们在存储过程中添加了commit
修改存储过程
CREATE OR REPLACE PROCEDURE DELETE_DPRECODE IS
BEGIN
DELETE C_DPRECODE
WHERE CAR_NUM IN (SELECT CAR_NUM FROM C_DPRECODE_C);
END;
再次执行插入语句,发现目的表中有插入数据了,但是没有表C_DPRECODE_C
中的数据
本站文章除注明转载/出处外,均为本站原创,转载前请务必署名,转载请标明出处 最后编辑时间为: 2021/08/15 15:55:08