Нарушение уникального ограничения при вставке: почему? (Оракул)

Я пытаюсь создать новую строку в таблице. В таблице есть два ограничения: одно относится к ключевому полю (DB_ID), другое ограничивает значение одним из нескольких значений поля ENV. Когда я делаю вставку, я не включаю поле ключа в качестве одного из полей, которые я пытаюсь вставить, но получаю эту ошибку:

unique constraint (N390.PK_DB_ID) violated

Вот SQL, который вызывает ошибку:

insert into cmdb_db 
   (narrative_name, db_name, db_type, schema, node, env, server_id, state, path) 
values 
   ('Test Database', 'DB', 'TYPE', 'SCH', '', 'SB01', 381, 'TEST', '')

Единственное, что мне удалось выяснить, это возможность того, что Oracle может пытаться назначить уже используемый DB_ID, если строки были вставлены вручную. Данные в этой базе данных каким-то образом были восстановлены/перемещены из производственной базы данных, но у меня нет подробностей о том, как это было сделано.

Есть предположения?


person Sean    schedule 27.09.2011    source источник


Ответы (3)


Предположительно, поскольку вы не предоставляете значение для столбца DB_ID, это значение заполняется на уровне строки до того, как триггер вставки определен в таблице. Этот триггер, предположительно, выбирает значение из последовательности.

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

Вы можете подтвердить это подозрение, взглянув на триггер, чтобы определить, какая последовательность используется, и выполнив

SELECT <<sequence name>>.nextval
  FROM dual

и сравнивая это с

SELECT MAX(db_id)
  FROM cmdb_db

Если, как я подозреваю, последовательность генерирует значения, которые уже существуют в базе данных, вы можете увеличивать последовательность до тех пор, пока она не будет генерировать неиспользуемые значения, или вы можете изменить ее, чтобы установить INCREMENT на что-то очень большое, получить nextval один раз и установить INCREMENT обратно в 1.

person Justin Cave    schedule 27.09.2011

Ваша ошибка выглядит так, будто вы дублируете уже существующий первичный ключ в своей БД. Вы должны изменить свой код sql, чтобы реализовать его собственный первичный ключ, используя что-то вроде ключевого слова IDENTITY.

CREATE TABLE [DB] (
    [DBId] bigint NOT NULL IDENTITY,
    ...

    CONSTRAINT [DB_PK] PRIMARY KEY ([DB] ASC),

); 
person Christopher Rayl    schedule 27.09.2011
comment
IDENTITY не является допустимым ключевым словом в Oracle. - person Justin Cave; 27.09.2011
comment
Это недопустимое утверждение для Oracle - person a_horse_with_no_name; 27.09.2011
comment
Вы, сэр, правы. Мое решение работает в SQL, а не в Oracle. Если вы хотите продублировать идентификатор SQL в Oracle, вам следует использовать последовательности ссылка @ Justin_Cave имеет прекрасную реализацию в своем ответе. - person Christopher Rayl; 27.09.2011

Похоже, вы не указываете значение для поля первичного ключа DB_ID. Если это первичный ключ, вы должны указать уникальное значение для этого столбца. Единственный способ не предоставлять его — создать триггер базы данных, который при вставке будет предоставлять значение, скорее всего, полученное из последовательности.

Если это восстановление из другой базы данных и в этом новом экземпляре есть последовательность, возможно, он пытается повторно использовать значение. Если старые данные имели уникальные ключи от 1 до 1000, а ваша текущая последовательность равна 500, то будут генерироваться уже существующие значения. Если для этой таблицы существует последовательность и она пытается ее использовать, вам потребуется согласовать значения в вашей таблице с текущим значением последовательности.

Вы можете использовать SEQUENCE_NAME.CURRVAL, чтобы увидеть текущее значение последовательности (если оно, конечно, существует)

person Brett McCann    schedule 27.09.2011
comment
В моей информации о базе данных говорится, что ключ должен генерироваться автоматически при вставке новой строки, поэтому я не указываю значение для DB_ID. Кроме того, этот же метод работает с другими таблицами в базе данных, которые похожи — у них есть автоматически сгенерированный ключ идентификатора. - person Sean; 27.09.2011
comment
Можете ли вы запросить словарь данных, чтобы узнать, существуют ли в новой среде необходимые триггеры/последовательности? Возможно, не все было перенесено из старой среды. - person Brett McCann; 27.09.2011