Dan*_*ses 4 sql oracle race-condition
考虑一个有多个课程注册请求的系统.我们需要一种方法来阻止系统中的重复注册.我创建了一个触发器,如下所示,但是当我同时从不同的连接获得两个请求(相隔ms)时,它们都被插入.我究竟做错了什么
create trigger enrollment_duplicates
before insert
on enrollment
for each row
begin
select count(*)
into cnt
from enrollment
where user = :new.user
and course = :new.course
and status = 'Enrolled';
if cnt > 0 then
raise_application_error(-20001, 'User already enrolled in course');
end if;
end;
Run Code Online (Sandbox Code Playgroud)
编辑:
如果我们使用户/课程成为一个独特的约束,这很容易,但事实并非如此.他们可以根据状态重新注册.
您需要一个唯一的索引.如果您说只有Enrolled一行但有许多行具有其他状态,则可以创建基于函数的索引
CREATE UNIQUE INDEX idx_stop_multiple_enrolls
ON enrollment( (case when status = 'Enrolled'
then user
else null
end),
(case when status = 'Enrolled'
then course
else null
end) );
Run Code Online (Sandbox Code Playgroud)
这需要的是,Oracle不包含在索引值时,所有列的优势NULL,因此指数只有条目行,其中的status是Enrolled.
注意,这USER是一个保留字(有一个内置函数USER)所以我假设你的实际列被命名为不同的东西.