我们有一个数据库表foo,
ID NUMBER(10,0) No 1
其中ID是主键。
有人写了一条插入语句
INSERT INTO foo (ID, ...) VALUES (foo_squ.NEXTVAL, ...)
其中foo_squ是squense。定义如下:
CREATE SEQUENCE "FOO_SQU" MINVALUE 0 MAXVALUE 9999999999 INCREMENT BY 1 START WITH 3331 NOCACHE NOORDER CYCLE ;
insert语句导致重复的主键错误。
要找出问题所在,我运行
select foo_squ.nextval from dual;
我得到339。我奔跑
select id from foo where id >= 338;
我得到338。
我创建了一个触发器来解决问题。
create or replace TRIGGER FOO_TRIGGER
BEFORE INSERT ON foo FOR EACH ROW
BEGIN
SELECT FOO_SQU.NEXTVAL
INTO :NEW.ID
FROM DUAL;
END;
使用触发器,ID字段不必在插入语句中。那将解决问题。但是,有人说触发器会导致性能问题。
什么是替代解决方案?
更新:
表中有一个时间戳。我们决定使用ID和时间戳的复合键来解决该问题。处理这个问题对我来说很奇怪。
答案 0 :(得分:0)
我相信您应该检查该值是否不再传递,因为正如您提到的,应用程序执行命令FOO_SQU.NEXTVAL且不增加其序列两次,可以添加一个if。
create or replace TRIGGER FOO_TRIGGER
BEFORE INSERT ON foo FOR EACH ROW
BEGIN
IF :NEW.ID is NULL THEN
SELECT FOO_SQU.NEXTVAL
INTO :NEW.ID
FROM DUAL;
END IF;
END;
如评论中所述,在Oracle中,您几乎不会迷失顺序,可能是应用程序使用了错误的代码。
您将序列用作插入或使用触发器的参数,我相信您不会看到任何实际的差异。