我有一个触发器自动但只在同一个会话中执行一次,然后什么都不做
CREATE OR REPLACE TRIGGER tdw_insert_unsus
BEFORE INSERT ON unsuscription_fact FOR EACH ROW
DECLARE
PRAGMA AUTONOMOUS_TRANSACTION;
v_id_suscription SUSCRIPTION_FACT.ID_SUSCRIPTION%TYPE;
v_id_date_suscription SUSCRIPTION_FACT.ID_DATE_SUSCRIPTION%TYPE;
v_id_date_unsuscription SUSCRIPTION_FACT.ID_DATE_UNSUSCRIPTION%TYPE;
v_suscription DATE;
v_unsuscription DATE;
v_live_time SUSCRIPTION_FACT.LIVE_TIME%TYPE;
BEGIN
SELECT id_suscription, id_date_suscription
INTO v_id_suscription, v_id_date_suscription
FROM(
SELECT id_suscription, id_date_suscription
FROM suscription_fact
WHERE id_mno = :NEW.ID_MNO
AND id_provider = :NEW.ID_PROVIDER
AND ftp_service_id = :NEW.FTP_SERVICE_ID
AND msisdn = :NEW.MSISDN
AND id_date_unsuscription IS NULL
ORDER BY id_date_suscription DESC
)
WHERE ROWNUM = 1;
-- calculate time
v_unsuscription := to_date(:NEW.id_date_unsuscription,'yyyymmdd');
v_suscription := to_date(v_id_date_suscription,'yyyymmdd');
v_live_time := (v_unsuscription - v_suscription);
UPDATE suscription_fact SET id_date_unsuscription = :NEW.id_date_unsuscription,
id_time_unsuscription = :NEW.id_time_unsuscription, live_time = v_live_time
WHERE id_suscription = v_id_suscription;
COMMIT;
EXCEPTION
WHEN NO_DATA_FOUND THEN
ROLLBACK;
END;
/
如果我插入的值在第一次或第二次工作时效果很好但是在不工作之后,但是如果我注销会话并且登录适用于第一次或第二次插入 有什么问题?,我用的是oracle 10g
答案 0 :(得分:4)
您正在使用自治事务来解决触发器无法查询其表本身的事实。您已经遇到臭名昭着的变异表错误,并且您发现将触发器声明为自治事务会使错误消失。
虽然没有运气,但这根本无法解决问题:
suscription_fact
表上的更改,它们是已提交,而您的主要交易不是并且可以回滚。所以你也失去了数据完整性。这就是为什么你不应该在自治事务中做任何业务逻辑。 (有合法的应用程序,但它们几乎完全限于记录/调试)。
在你的情况下,你应该:
suscription_fact
中存储的旧值更新时才更新id_date_unsuscription
。我强烈建议在这里使用(2)。不要使用触发器来编写业务逻辑。他们很难写,没有错误,更难以维护。使用程序可以保证所有相关代码都分组在一个地方(包或程序),易于阅读和遵循,并且没有不可预见的后果。