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

Запросы, планы, оптимизация запросов, ...

Модераторы: kdv, CyberMax

Ответить
PROF
Сообщения: 12
Зарегистрирован: 29 ноя 2004, 05:18

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

Сообщение PROF » 27 янв 2005, 06:37

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

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

Заранее, please!

eugeney
Сообщения: 79
Зарегистрирован: 29 окт 2004, 18:51

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

Сообщение eugeney » 27 янв 2005, 09:47

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!='....'

kdv
Forum Admin
Сообщения: 6595
Зарегистрирован: 25 окт 2004, 18:07

Сообщение kdv » 27 янв 2005, 10:14

PK не меняют. Хоть и есть всякие каскады и т.п., но считается что идентификатор записи не должен меняться, пока запись существует.

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

Merlin
Динозавр IB/FB
Сообщения: 1502
Зарегистрирован: 27 окт 2004, 11:44

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

Сообщение Merlin » 27 янв 2005, 12:20

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:

Ответить