我有一个名为LOCK
的表,我想确保不多于一个具有给定名称和类型WRITE
的行。尽管允许多行类型为READ
且名称相同的行,但前提是不存在名称相同且类型为WRITE
的行。
create table "LOCK"
(
"LOCK_ID" NUMBER(19,0) NOT NULL,
"NAME" VARCHAR2(255 CHAR),
"TYPE" VARCHAR2(32 CHAR),
CONSTRAINT "SYS_LOCK_PK" PRIMARY KEY ("LOCK_ID")
);
插入行必须是原子的,例如,没有查询时会根据查询结果插入以下插入内容(因为它可能同时发生了变化)。
为了确保原子性,我创建了一个触发器来检查最初提到的条件(失败时引发错误),该条件有时会终止于各种无效状态,例如两行WRITE
。
如果按顺序执行插入操作,则触发器可以正常工作,这会导致假设插入+触发器不是原子过程,如果是,那么有没有安全的方法来解决我的问题?
这是触发因素:
create or replace trigger "LOCK_TRIGGER"
before insert on "LOCK"
referencing NEW AS NEW
for each row
declare
c integer := 0;
begin
select count(*) into c from "LOCK" where (:NEW.typ = 'WRITE' and name = :NEW.name) or (:NEW.typ = 'READ' and name = :NEW.name and typ = 'WRITE');
if (c > 0) then
raise_application_error(-20634, 'Nope!');
end if;
end;
答案 0 :(得分:1)
对于多用户环境,Trigger在这里没有帮助。您需要序列化对特定锁名称的访问。对于这种情况,我将使用自定义锁。数据库包dbms_lock用于此目的。您可以创建一个执行以下操作的函数:
希望有帮助。