Ошибка ORA-00001: unique constraint violated — причины и решение в Oracle DB
При выполнении операций INSERT или UPDATE транзакция аварийно прерывается со следующим сообщением:
ORA-00001: unique constraint (SCHEMA_NAME.CONSTRAINT_NAME) violated- Сбой загрузки данных через ETL/ELT процессы, интеграционные шины или вызовы PL/SQL пакетов.
- В прикладных журналах (включая 1С при работе с Oracle) регистрируются ошибки вставки дублирующихся записей.
- Откат текущей транзакции (statement-level rollback) с сохранением предыдущих незафиксированных изменений.
1. Идентификация таблицы и колонок с ограничением
Выполните запрос к системному словарю данных для определения полей, входящих в нарушенный констрейнт:
SELECT c.owner, c.table_name, c.constraint_name, cc.column_name, cc.position
FROM all_constraints c
JOIN all_cons_columns cc ON c.owner = cc.owner AND c.constraint_name = cc.constraint_name
WHERE c.constraint_name = 'CONSTRAINT_NAME'
ORDER BY cc.position;2. Поиск конфликтующих строк в таблице
SELECT column1, column2, COUNT(*)
FROM SCHEMA_NAME.TABLE_NAME
GROUP BY column1, column2
HAVING COUNT(*) > 1;3. Исправление рассинхронизации Sequence (Последовательностей)
Если первичный ключ генерируется объектом SEQUENCE, его текущее значение может отставать от фактического максимума в таблице:
-- 1. Определение максимального ID в таблице
SELECT NVL(MAX(id_column), 0) FROM SCHEMA_NAME.TABLE_NAME;
-- 2. Проверка следующего значения sequence
SELECT sequence_name, last_number FROM all_sequences WHERE sequence_name = 'SEQ_NAME';
-- 3. Выравнивание sequence через RESTART (Oracle 12c+)
ALTER SEQUENCE SCHEMA_NAME.SEQ_NAME RESTART WITH 105420;4. Использование безопасной вставки (MERGE / UPSERT)
MERGE INTO target_table t
USING (SELECT :id AS id, :val AS val FROM dual) s
ON (t.id = s.id)
WHEN MATCHED THEN
UPDATE SET t.val = s.val
WHEN NOT MATCHED THEN
INSERT (id, val) VALUES (s.id, s.val); Частые вопросы (FAQ)
Почему ORA-00001 возникает при параллельной вставке одинаковых данных?
Если две параллельные транзакции одновременно пытаются вставить одинаковый уникальный ключ, первая успешно блокирует строку, а вторая ждет завершения. После COMMIT первой транзакции вторая завершается ошибкой ORA-00001.
Как временно пропустить ошибочные строки при массовой вставке (Bulk Insert)?
Используйте конструкцию DBMS_ERRLOG: создайте таблицу логов с помощью DBMS_ERRLOG.CREATE_ERROR_LOG, затем добавьте в INSERT фразу LOG ERRORS INTO errlog_table ('INSERT_OP') REJECT LIMIT UNLIMITED.
Как влияет индексация NULL-значений на уникальные ограничения?
В стандарте Oracle B-Tree индекс не индексирует строки, где все столбцы уникального ключа равны NULL. Поэтому несколько строк с NULL в одном поле разрешены, если в ключе нет NOT NULL ограничения или других не-NULL столбцов.
Можно ли перевести уникальное ограничение в отложенный режим (DEFERRABLE)?
Да, если ограничение создано с параметром DEFERRABLE INITIALLY DEFERRED, проверка уникальности будет производиться не во время выполнения INSERT/UPDATE, а только в момент выполнения команды COMMIT.