我的问题是我一直试图通过简单地获取表的主键的最大值来插入新记录然后将其添加1,我之前的最大值是100152,当我插入一次时一切都很好但是,当我尝试插入新记录时,我收到一条错误消息,说我正在插入副本。我后来发现,即使我已经插入了主键100153的行,我从中得到的最大ID仍然是100152.我知道存在100153记录,但为什么我不能选择它就好像它没有& #39; t存在?这是隐藏还是什么?在此先感谢那些愿意回答的人,我真的很困惑。
答案 0 :(得分:1)
我可以假设,你有两个并发会话:
让我们创建一个表并在其中插入第一行:
SESSION1:
SQL> conn scott
Enter password:
Connected.
SQL> create table ttt (
2 col1 number(10) primary key
3 );
Table created.
SQL> insert into ttt values (1);
1 row created.
SQL> commit;
会话2:
SQL> conn scott
Enter password:
Connected.
SQL> select * from ttt;
no rows selected
SQL> select * from ttt;
COL1
----------
1
让我们使用ttt
表的最大值来生成下一个值的主键值:
SESSION1:
SQL> insert into ttt select max(col1) + 1 from ttt;
1 row created.
会话2:
SQL> insert into ttt select max(col1) + 1 from ttt;
Session2挂起,因为它被Session1阻止。
让我们提交session1:
SESSION1:
SQL> commit;
Commit complete.
我可以在Session2中看到这一点:
SQL> insert into ttt select max(col1) + 1 from ttt;
insert into ttt select max(col1) + 1 from ttt
*
ERROR at line 1:
ORA-00001: unique constraint (SCOTT.SYS_C0010855) violated
SQL> select * from ttt;
COL1
----------
1
2
因此,使用当前最大值生成下一个主键值是个坏主意。为此,您必须创建一个序列:
SESSION1:
SQL> create sequence ttt_pk_seq
2 start with 3
3 /
Sequence created.
SQL> insert into ttt values (ttt_pk_seq.nextval);
1 row created.
会话2:
SQL> insert into ttt values (ttt_pk_seq.nextval);
1 row created.
SESSION1:
SQL> commit;
会话2:
SQL> select * from ttt;
COL1
----------
1
2
3
4
这是可能的,因为序列的处理总是在自治事务中执行。
P.S。:要提高应用的效果,请使用reverse key index作为主键
答案 1 :(得分:0)
更好的设计方法是使用Trigger和Sequence自动递增Row的值。 序列示例:
CREATE OR REPLACE SEQUENCE ACCOUNT_SEQ
START WITH 1 -- for you case start with the maximum value of the column value
INCREMENT BY 1;
触发器示例:
CREATE OR REPLACE TRIGGER TRIGGER1
BEFORE INSERT ON ACCOUNTS -- tablename
FOR EACH ROW
WHEN (new.ID IS NULL) -- column name of the table
BEGIN
SELECT ACCOUNTS_SEQ.NEXTVAL
INTO :new.ID
FROM dual;
END;
/