ORA-00001:唯一约束:手动设置主键

时间:2016-05-21 10:29:14

标签: database oracle hibernate

我们有一个Oracle数据库,我们有一个表格,用于存储大量数据。 该表有一个主键,通常这些主键只是在插入新行时创建的。

但现在我们需要使用某些固定的主键手动将数据插入此表。无法更改这些主键。

例如:

我们的表已经有20个条目,主键1到20。 现在我们需要使用主键21到23手动添加数据。

当有人想使用我们的标准方法输入一行时,插入过程将因以下原因而失败:

Caused by: java.sql.BatchUpdateException: ORA-00001: Unique Constraint (VDMA.SYS_C0013552) verletzt

    at oracle.jdbc.driver.OraclePreparedStatement.executeBatch(OraclePreparedStatement.java:10500)
    at oracle.jdbc.driver.OracleStatementWrapper.executeBatch(OracleStatementWrapper.java:230)
    at org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:70)
    at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:268)

我完全理解这一点:创建下一个主键的数据库例程(序列)失败,因为已经采用了下一个主键。

但是:我如何告诉我的序列再次查看表格并意识到下一个主键是24而不是21?

更新

ID需要保持不变的原因是因为使用包含ID的链接使用Web Interface访问记录。 因此,要么我们更改将旧ID映射到新ID的实现,要么将ID保留在数据库中。

UPDATE2

找到一个解决方案:由于我们使用的是hibernate,因此只有一个序列填充所有表。因此,在我寻找答案的那4天中,主键变得如此之高,以至于我可以保存导入所有数据。

1 个答案:

答案 0 :(得分:1)

  

如何告诉我的序列再次查看表格并意识到下一个主键是24而不是21?

在Oracle中,序列不知道您打算将它用于任何特定的表。所有序列都知道它的当前值,增量,最大值等等。因此,您无法告诉序列查看表,但您可以告诉存储过程检查表,然后将序列递增到主键的最大值之后。换句话说,如果您确实坚持使用非序列值手动更新主键,那么您的代码需要检查PK中的非序列值,并在使用序列生成新PK之前使序列加快。

这里有一些简单的东西可以用来将序列带到它需要的位置:

select testseq.nextval from dual; 

每次运行时,序列都会增加1.将其粘贴在for循环中并运行直到testseq.currval为止所需的位置。

话虽如此,我同意@a_horse_with_no_name和@EdStevens。如果必须手动插入行,至少在insert中使用sequence_name.nextval而不是像'21'这样的文字。像这样:

 create table testtab (testpk number primary key, testval number);

 create sequence testseq start with 1 increment by 1;

 insert into testtab values (testseq.nextval, '12');
 insert into testtab values (testseq.nextval, '123');
 insert into testtab values (testseq.nextval, '1234');
 insert into testtab values (testseq.nextval, '12345');
 insert into testtab values (testseq.nextval, '123456');

 select * from testtab;

 testpk  testval
 2  12
 3  123
 4  1234
 5  12345
 6  123456