Rails: нарушение ограничений Oracle
Я делаю ремонтные работы на сайте Rails, который я унаследовал; он управляется базой данных Oracle, и у меня есть доступ как к разработке, так и к производственной установке сайта (каждая со своей собственной базой данных Oracle). Я сталкиваюсь с ошибкой Oracle при попытке вставить данные на рабочий сайт, но не на сайт разработчика:
ActiveRecord::StatementInvalid (OCIError: ORA-00001: unique constraint (DATABASE_NAME.PK_REGISTRATION_OWNERSHIP) violated: INSERT INTO registration_ownerships (updated_at, company_ownership_id, created_by, updated_by, registration_id, created_at) VALUES ('2006-05-04 16:30:47', 3, NULL, NULL, 2920, '2006-05-04 16:30:47')):
/usr/local/lib/ruby/gems/1.8/gems/activerecord-oracle-adapter-1.0.0.9250/lib/active_record/connection_adapters/oracle_adapter.rb:221:in `execute'
app/controllers/vendors_controller.rb:94:in `create'
Насколько я могу судить (я использую Navicat в качестве клиента Oracle), схема БД для сайта разработчика идентична схеме действующего сайта. Я не эксперт по Oracle; Может кто-нибудь пролить свет на то, почему я получаю ошибку в одной установке, а не в другой?
Кстати, таблицы dev и production registration_ownerships заполнены большим количеством данных, включая повторяющиеся записи для country_ownership_id (управляемый индексом PK_REGISTRATION_OWNERSHIP). Пожалуйста, дайте мне знать, если вам нужна дополнительная информация для устранения неполадок. Извините, я еще не дал больше, но я просто не был уверен, какие детали будут полезны.
ОБНОВЛЕНИЕ: я попытался удалить ограничение на производственном сервере, но это не имело никакого эффекта; Я также не хотел отказываться от индекса, потому что я не уверен, каковы могут быть последствия, и я не хочу делать производство менее стабильным, чем оно уже есть.
Любопытно, что я попытался вручную выполнить SQL, который выдавал ошибку, и Oracle принял оператор вставки (хотя мне пришлось обернуть даты в вызовах to_date() строковыми литералами, чтобы обойти "ORA-01861: литерал не совпадает" строка формата "ошибка". Что здесь может происходить?
4 ответа
Как оказалось, в каталоге была резервная копия модели "регистрации"; хотя у него было другое имя ("registrations_2349871.rb" или что-то в этом роде), Rails запускал всю функциональность модели (сохранение, проверка и т. д.) дважды, отсюда и нарушение ключевого ограничения! Я никогда не видел такого поведения раньше. Удаление мошеннического файла решило проблему.
Основываясь на названии ограничения, PK_REGISTRATION_OWNERSHIP
, у вас есть нарушение первичного ключа. Если эти базы данных не поддерживают эти данные в непрерывном режиме, что-то / кто-то уже вставил запись в registration_ownerships
таблица в вашей производственной базе данных с company_ownership_id
= 2 & registration_id
= 2920. (Я предполагаю, на основе специфики на основе имен)
Если этот конкретный набор значений должен существовать в производственной базе данных,
1) проверьте, что то, что уже есть, не то, что вы пытаетесь вставить. если это так, все готово.
2) Если вам нужно вставить пример данных как есть, вам нужно изменить существующие данные и повторно вставить их (и все зависимые / ссылающиеся записи), а затем вы можете вставить свои значения.
Если вы запросите таблицу и не найдете подходящих строк, причиной может быть одно из следующих:
- Сессия пытается вставить строку дважды.
- Другой сеанс вставил строку, но еще не зафиксирован.
Также проверьте, что состояние уникального ограничения одинаково между dev и prod. Возможно, тот, что на dev, помечен как неподтвержденный - проверьте, что индекс существует на dev и является уникальным индексом (примечание: в Oracle можно иметь уникальное ограничение, проверяемое неуникальным индексом).
Внимательно посмотрите на базовый уникальный индекс для ограничения. Причина, по которой снятие ограничения ничего не меняет, состоит в том, что индекс остается, и это уникальный индекс. Что ниже говорит вам об индексах в обеих средах? Действительны ли оба индекса? Оба определены одинаково? Они оба на самом деле уникальны?
SELECT ai.table_name, ai.index_name, ai.uniqueness, aic.column_name, ai.status
FROM all_constraints ac JOIN all_indexes ai ON (ac.index_name = ai.index_name)
JOIN all_ind_columns aic ON (ai.index_name = aic.index_name)
WHERE ac.owner = 'YOUR_USER'
AND ac.constraint_name = 'PK_REGISTRATION_OWNERSHIP'
ORDER BY ai.index_name, column_position;