2016-05-21 2 views
0

У нас есть база данных Oracle, и у нас есть таблица, в которой мы храним много данных. В этой таблице есть первичный ключ, и обычно эти первичные ключи только создаются при вставке новой строки.ORA-00001: Уникальная константа: установка основных ключей вручную

Но теперь нам нужно вручную вставить данные в эту таблицу с помощью определенных фиксированных первичных ключей. Невозможно изменить эти первичные ключи.

Так, например:

Наша таблица имеет уже 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) 

Я полностью понимаю this: Процедура (последовательность) базы данных, которая создает следующий первичный ключ, терпит неудачу, потому что уже сделан следующий первичный ключ.

Но: Как я могу рассказать о своей последовательности, чтобы снова взглянуть на таблицу и понять, что следующий первичный ключ равен 24, а не 21?

UPDATE

Причина, почему идентификаторы должны остаться такой же, потому что получает доступ к записи с помощью веб-интерфейса с помощью ссылки, которые содержат идентификатор. Таким образом, либо мы меняем реализацию, сопоставляя старые идентификаторы с новыми идентификаторами, либо сохраняем идентификаторы в базе данных.

UPDATE2

Найдено решение: Поскольку мы используем спящий режим, только одна последовательность заполнения всех таблиц. Таким образом, первичные ключи в те 4 дня, когда я искал ответ, были настолько высокими, что я мог с уверенностью импортировать все данные.

+2

«* Теперь нам нужно добавить данные вручную с помощью первичных ключей от 21 до 23 *» - не делайте этого. Используйте эту последовательность, чтобы вставить эти значения. Все остальное вызовет у вас проблемы. Вы не можете заставить последовательность «смотреть» на таблицу. Единственный способ изменить значение последовательности - это вызвать 'nextval' или удалить и повторно создать последовательность с новым стартовым значением. –

+0

Может ли воссоздать последовательность помощи? – Breiti

+2

Продвиньте последовательность, один раз, к следующему доступному идентификатору на основе максимального значения, которое вы вставили вручную. –

ответ

1

Как я могу рассказать о своей последовательности, чтобы снова взглянуть на таблицу и понять, что следующий первичный ключ равен 24, а не 21?

В Oracle последовательность не знает, что вы собираетесь использовать ее для какой-либо конкретной таблицы. Вся последовательность знает его текущее значение, его прирост, его maxval и так далее. Таким образом, вы не можете определить последовательность, чтобы посмотреть на таблицу, но вы можете сказать своей хранимой процедуре, чтобы проверить таблицу, а затем увеличивать последовательность за пределами максимального значения первичного ключа. Другими словами, если вы действительно настаиваете на том, чтобы вручную обновлять первичный ключ с не-последовательными значениями, тогда ваш код должен проверять значения без последовательности в PK и получать последовательность до скорости, прежде чем она будет использовать последовательность для генерации новой PK.

Вот что-то простое вы можете использовать, чтобы принести последовательность до того, где она должна быть:

select testseq.nextval from dual; 

Каждый раз, когда вы запускаете его приращения последовательности от 1. Придерживайтесь его в цикле и запустить его до testseq.currval, где вам это нужно.

Сказав это, я согласен с @a_horse_with_no_name и @EdStevens. Если вам нужно вставлять строки вручную, по крайней мере используйте 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 
+0

Большое спасибо за ваш ответ, но, к сожалению, эти идентификаторы должны остаться то же самое, потому что клиент использует сохраненные URL для доступа к ним :( – Breiti

+0

Привет @Breiti, идентификаторы, которые вы уже назначили, должны оставаться неизменными. Но в следующий раз, когда вам нужно генерировать новые идентификаторы вручную, используйте последовательность, используя «testseq. nextval "во вставке вместо того, чтобы записывать число во вставке. Если вы запустите' select testseq.nextval из dual; 'достаточно времени, чтобы привести последовательность до того места, где она должна быть, это не повлияет ни на одну из уже назначенных Идентификаторы. –

Смежные вопросы