Страница 1 из 1

Как изменить ключевое поле

Добавлено: 27 янв 2005, 06:37
PROF
Привет всем!
Имеется база сконструированная т.о.:
имеется главная таблица OBJECT с ключем ID, и имеется большое число таблиц, связанных с ней по этому ID. Т. е., ситуация стандартная. Но есть огромное желание этот ID менять (в контретной записи, или по всей таблице разом). Лично я вижу два способа решения проблемы:
1. Каким-то образом временно отключить все CONSTRANT-ы для OBJECT (но есть ли механизмы для этого типа как ACTIVE/INACTIVE для триггеров). Я накопал только, что нужно просто DROP-пить их и после всех махинаций создавать снова.
2. Написать триггер AFTER_UPDATE, в котором тем или иным образом каскадно заменить ID во всех подчиненых таблицах.

Подскажите, какой способ предпочтительней, или я вообще занимаюсь Ф-ней.

Заранее, please!

Re: Как изменить ключевое поле

Добавлено: 27 янв 2005, 09:47
eugeney
PROF писал(а):Привет всем!
Имеется база сконструированная т.о.:
имеется главная таблица OBJECT с ключем ID, и имеется большое число таблиц, связанных с ней по этому ID. Т. е., ситуация стандартная. Но есть огромное желание этот ID менять (в контретной записи, или по всей таблице разом). Лично я вижу два способа решения проблемы:
...
Подскажите, какой способ предпочтительней, или я вообще занимаюсь Ф-ней.
Заранее, please!
Вообщето менять primary key не принято.
Даже если ты отключиш тригера тебе это не сильно помоежет. В этот момент могут произойти следующие коллизи и способы выхода из них.

- пересчение ID в один момент ты не можеш сделать update ... set id=id+1, уникальный индекс не позволит. Решение делаеш это в 2 захода set id=-id set id=1-id.
- при обновлении PK следует поменять FK, решается просто в момент создания FK добавь on update cascade
- твои личные тригерры будут срабатывать при обновлении, решаеться добавлением специального пользователя и проверка в тригере corrent_user!='....'

Добавлено: 27 янв 2005, 10:14
kdv
PK не меняют. Хоть и есть всякие каскады и т.п., но считается что идентификатор записи не должен меняться, пока запись существует.

каскадно обновить-удалить можно, только триггером BEFORE update/delete, а не after. существующие constraint удалять необязательно.

Re: Как изменить ключевое поле

Добавлено: 27 янв 2005, 12:20
Merlin
PROF писал(а):Привет всем!
Имеется база сконструированная т.о.:
имеется главная таблица OBJECT с ключем ID, и имеется большое число таблиц, связанных с ней по этому ID. Т. е., ситуация стандартная. Но есть огромное желание этот ID менять (в контретной записи, или по всей таблице разом). Лично я вижу два способа решения проблемы:
1. Каким-то образом временно отключить все CONSTRANT-ы для OBJECT (но есть ли механизмы для этого типа как ACTIVE/INACTIVE для триггеров). Я накопал только, что нужно просто DROP-пить их и после всех махинаций создавать снова.
2. Написать триггер AFTER_UPDATE, в котором тем или иным образом каскадно заменить ID во всех подчиненых таблицах.

Подскажите, какой способ предпочтительней, или я вообще занимаюсь Ф-ней.
!
Именно последнее. Желание менять первичный ключ говорит скорее всего о том, что в качестве ПК используется атрибут, а не однозначный идентификатор записи. Часто в эту ловушку попадают любители естественных ключей на базовых справочниках. Если так, то я бы советовал один разок напрячься и сделать ПК и соотвественно ФК на других таблицах на искусственном id и менять тот атрибут, который сейчас назанчен ПК в любой момент по вкусу и без всяких каскадов. На триггерах не получится - в момент апдейт должны существовать записи и со старым и с новым ПК, иначе фигушки. То есть, надо делать не апдейт, а инсёрт-апдейт деталей-делет старой. Есть примочка специально для мазохистов - Foreign Key On Update Cascade - который автоматически делает то, что ты хочешь, втихую нарушая в момент выполнения reference integrity. Но тормоза при этом получишь конкретные, не только на самом апдейте, но и на последующей работе из-за того, что при этом образуются горы мусора и в данных и в индексах. Так что лучше сделать один раз по уму.
PROF писал(а): Заранее, please!
Заранее, thanks :lol: