Подтвердить что ты не робот

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

Я пытаюсь создать новую строку в таблице. В таблице есть два ограничения: одно находится в ключевом поле (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, если строки были вставлены вручную. Данные в этой базе данных были каким-то образом восстановлены/перенесены из производственной базы данных, но у меня нет информации о том, как это было сделано.

Любые мысли?

4b9b3361

Ответ 1

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

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

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

SELECT <<sequence name>>.nextval
  FROM dual

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

SELECT MAX(db_id)
  FROM cmdb_db

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

Ответ 2

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

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

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

Ответ 3

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

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

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

);