Изменить значение первичного ключа в Oracle - PullRequest
3 голосов
/ 15 февраля 2011

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

Ответы [ 7 ]

6 голосов
/ 15 февраля 2011

Более простой альтернативой является вставка новой строки и удаление старой. (Перед удалением обновите все ссылки на строки в других таблицах)

4 голосов
/ 15 февраля 2011

Нет встроенного ОБНОВЛЕНИЯ КАСКАДА, если это то, что вам нужно. Вам нужно было бы сделать что-то вроде отключения любых ограничений FK; запустить операторы UPDATE; повторно включите ограничения.

Обратите внимание, что обновление первичных ключей (как правило, всегда) является плохой идеей.

2 голосов
/ 15 февраля 2011

Вам нужно будет отключить ограничения внешнего ключа перед изменением значений первичного ключа, а затем снова включить их.

Если вы на самом деле хотите реализовать вместо этого функцию «каскадного обновления», см. Пакет обновлений Tom Kyte

1 голос
/ 27 октября 2014

Это возможно даже без отключения ограничений, в случае, если вы хотите только поменять местами ключи (которые также являются подмножеством изменений, поэтому они все еще могут быть ответом на ваш вопрос).Я написал пример здесь: https://stackoverflow.com/a/26584576/1900739

update MY_TABLE t1
set t1.MY_KEY = (case t1.MY_KEY = 100 then 101 else 100 end)
where t1.MYKEY in (100, 101)
0 голосов
/ 07 апреля 2016

Другой способ сделать это - изменить ограничения внешнего ключа так, чтобы проверка ограничения откладывалась до тех пор, пока вы не совершите фиксацию - т.е. вместо того, чтобы Oracle проверял ограничения оператор за оператором, он будет делать это транзакцией -transaction.

Обратите внимание, что вы не можете сделать это с помощью оператора "alter table", но вы можете удалить и заново создать ограничение внешнего ключа для отсрочки, т.е.:

alter table <table name> drop constraint <FK constraint name>;
alter table <table name> add constraint <FK constraint name> foreign key .... initially deferrable;

Как только вы это сделаете, просто обновите таблицы в любом порядке и зафиксируйте - в какой момент, либо:

  1. Все ваши ограничения ФК выполнены, и все счастливы; или
  2. Вы где-то нарушили ограничение FK - вы получите ошибку, и вам придется исправить данные и зафиксировать или откатить.

Обратите внимание, что эта функция довольно безопасна, поскольку Oracle не допускает грязного чтения, поэтому они будут видеть результаты ваших обновлений только после того, как вы подтвердите. Таким образом, с точки зрения любого другого сеанса ссылочная целостность представляется сохраненной.

Кроме того, это разовое изменение, поэтому вам не нужно выполнять DDL каждый раз, когда вы хотите обновить первичные ключи.

0 голосов
/ 29 февраля 2016

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

Генерация скрипта SELECT 'alter table ' || uc.table_name|| ' disable constraint '|| uc.constraint_name|| ' ;' FROM user_constraints uc inner join user_cons_columns ucc on uc.constraint_name = ucc.constraint_name where column_name = 'MYCOLUMN_USED_AS_FOREIGN_KEY' and constraint_type='R' Скопируйте / вставьте сгенерированный скрипт и запустите его

alter table MYTABLE1 disable constraint FK_MYTABLE1 ; alter table MYTABLE2 disable constraint MYTABLE2 ; alter table MYTABLE3 disable constraint FK3_MYTABLE3 ; ...

Затем обновите ваши значения PK: update MYTABLE1 set MYFIELD= 'foo' where MYFIELD='bar'; update MYTABLE2 set MYFIELD= 'foo' where MYFIELD='bar'; update MYTABLE3 set MYFIELD= 'foo' where MYFIELD='bar'; commit; Сгенерируйте сценарий включения ограничений:

SELECT 'alter table ' || uc.table_name|| ' enable constraint '|| uc.constraint_name|| ' ;' FROM user_constraints uc inner join user_cons_columns ucc on uc.constraint_name = ucc.constraint_name where column_name = 'MYCOLUMN_USED_AS_FOREIGN_KEY' and constraint_type='R'

0 голосов
/ 27 октября 2014

Да, есть способ выполнить каскадное обновление в Oracle, даже внутри транзакции (что не относится к опции включения / отключения ограничений).Однако вам придется реализовать это самостоятельно.Это можно сделать с помощью триггеров до / после обновления строки.

Это возможно из-за того, что триггеры выполняются до проверки каких-либо ограничений.(Ну, по крайней мере, в Oracle 11.2 это было правдой. Не проверялось на 12.1, но я искренне верю, что оно не изменилось.).

...