我们有一个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天中,主键变得如此之高,以至于我可以保存导入所有数据。
答案 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