Как мне создать съемный внешний ключ? - PullRequest
0 голосов
/ 14 ноября 2011

В основном ситуация выглядит так (упрощенно, псевдокод):

У меня 2 ТАБЛИЦЫ на человека и страну.

Таблица персон:

KEY INT ID, STRING NAME, STRING COUNTRY

Таблица страны:

KEY INT ID, STRING COUNTRY_NAME

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

Для меня имеет смысл, что этот человек должен иметь ссылку на внешний ключ для страны, но поскольку клиент имеет контрольпо сравнению с тем, что появляется в таблице «Страна», они хранятся в виде отдельных таблиц, потому что вы не можете просто удалить использованные страны (ссылочная целостность и все).Это аргумент, выдвинутый моим коллегой, чтобы в этом случае не использовать внешние ключи, но я чувствую, что должно быть лучшее решение этой проблемы. Итак, прав ли мой коллега или есть лучшее решение?

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

Ответы [ 3 ]

1 голос
/ 14 ноября 2011

Вы можете указать в качестве опции для FOREIGN KEY, что делать при удалении записи из таблицы, на которую ссылаются:1006 * Как правило, вы должны использовать внешние ключи.Например, почему должна быть возможность удалить страну, если люди ссылаются на нее?Без внешнего ключа необходимо вручную проверять наличие ссылок.

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

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

1 голос
/ 14 ноября 2011

Создайте неактивный столбец, данные для исторических записей затем покажут округ, выбранный первоначально (или его обновленное значение, см. Ниже), и в раскрывающемся списке можно настроить отображение только активных стран. Ни при каких обстоятельствах вы не должны снимать ограничение внешнего ключа. Это рецепт для проблем целостности данных.

Установка на нулевую идею, как правило, тоже плохая. Вы не хотите терять данные о стране, в которой находится человек.

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

0 голосов
/ 14 ноября 2011

База данных уже разработана для обработки записей, на которые все еще ссылаются внешние ключи.

Вам все равно следует использовать внешний ключ и указать, как вы хотите, чтобы он вел себя с on delete.Если вы хотите разрешить удаление записей (стран), на которые все еще ссылаются (по лицам), используйте

foreign key country_id references countries(id)
    on delete set null;

Если вы хотите, чтобы внешний ключ предотвращал исчезновение указанных стран, оставьтепредложение on delete и попытки удалить страны, на которые все еще есть ссылки, потерпят неудачу.Это обычно желаемое поведение;попытки перевести базу данных в недопустимое состояние в случае сбоя .

Если для внешнего ключа связанной записи задано значение null или предотвращено удаление указанной записи, внешний ключ по-прежнему применяетсяи поддерживает ссылочную целостность.Это их работа, и они довольно хороши в этом.

...