楼主贴的变量名错误太多,只好假设编译正确。最好先确保 startid <= endidupdate试试where startid<=:new.endid and endid>=:new.startid 然后判断ll_have>=2
这个过程是我按照题目的例子改的,没完全改好,其中new_rowid := :old.rowid应该是old_rowid := :old.rowid; 这句话的意思就是将本次更新的当前记录的最新值与除当前记录外的记录进行比较是否有交叉。 但是执行 old_rowid := :old.rowid; new_startid := :new.startid; new_endid := :new.endid; select count(*) into ll_have from tab1 where startid <= new_endid and endid >= new_startid and rowid <> old_rowid;--执行报错ora-04091
-- 得用带“自治事务”的触发器,代码如下: create table tab1(r_id number, startid number, endid number);create or replace trigger t_tab1_idcheck before insert or update on tab1 for each row declare PRAGMA AUTONOMOUS_TRANSACTION; ll_have number; begin if inserting then select count(1) into ll_have from tab1 where startid <= :new.endid and endid >= :new.startid; --执行成功 if (ll_have > 0) then raise_application_error(-20010,'error'); end if; end if; if updating then select count(*) into ll_have from tab1 where startid <= :new.endid and endid >= :new.startid and rowid <> :old.rowid; --执行报错 if (ll_have > 0) then raise_application_error(-20010, 'error'); end if; end if; end; /insert into tab1(r_id,startid,endid) values(1,1,1); insert into tab1(r_id,startid,endid) values(2,3,4); insert into tab1(r_id,startid,endid) values(3,5,8); commit;insert into tab1(r_id,startid,endid) values(4,2,2); commit;insert into tab1(r_id,startid,endid) values(5,9,12);commit;insert into tab1(r_id,startid,endid) values(6,2,3); commit;insert into tab1(r_id,startid,endid) values(7,6,7); commit;
然后判断ll_have>=2
这个过程是我按照题目的例子改的,没完全改好,其中new_rowid := :old.rowid应该是old_rowid := :old.rowid;
这句话的意思就是将本次更新的当前记录的最新值与除当前记录外的记录进行比较是否有交叉。
但是执行 old_rowid := :old.rowid;
new_startid := :new.startid;
new_endid := :new.endid;
select count(*)
into ll_have
from tab1
where startid <= new_endid
and endid >= new_startid
and rowid <> old_rowid;--执行报错ora-04091
create table tab1(r_id number, startid number, endid number);create or replace trigger t_tab1_idcheck before insert or update
on tab1 for each row
declare
PRAGMA AUTONOMOUS_TRANSACTION;
ll_have number;
begin
if inserting then
select count(1)
into ll_have
from tab1
where startid <= :new.endid
and endid >= :new.startid; --执行成功
if (ll_have > 0) then
raise_application_error(-20010,'error');
end if;
end if; if updating then
select count(*)
into ll_have
from tab1
where startid <= :new.endid
and endid >= :new.startid
and rowid <> :old.rowid; --执行报错
if (ll_have > 0) then
raise_application_error(-20010, 'error');
end if;
end if;
end;
/insert into tab1(r_id,startid,endid)
values(1,1,1);
insert into tab1(r_id,startid,endid)
values(2,3,4);
insert into tab1(r_id,startid,endid)
values(3,5,8);
commit;insert into tab1(r_id,startid,endid)
values(4,2,2);
commit;insert into tab1(r_id,startid,endid)
values(5,9,12);commit;insert into tab1(r_id,startid,endid)
values(6,2,3);
commit;insert into tab1(r_id,startid,endid)
values(7,6,7);
commit;
或根据endid和startid字段范围分区,再创建局部分区索引!
这个已经在CHECK里限制了update试试where startid<=:new.endid and endid>=:new.startid
然后判断ll_have>=2
这个count(*)>=2有问题,如果将第2行的值3,4改为3,5的确count=2,若改为1,2,count=1,不符合要求。
正解,之前也百度了ora-04091,没有认真的体会“自治事务”,现在大概了解了:
这是oracle的安全机制,在更新时确保新数据不被脏读或破坏,如果确定没有问题,
加一条PRAGMA AUTONOMOUS_TRANSACTION,告诉oracle解除该程序段的安全机制。谢谢luoyoumou,结贴!
after update触发时,记得是查到新数据。
after update触发时,记得是查到新数据。
谢谢!我需要在before update时触发,要不然业务处理起来比较麻烦