#sql #oracle #foreign-keys #primary-key
#sql #Oracle #внешние ключи #первичный ключ
Вопрос:
Я создал таблицу в oracle, в которой есть один FK, который ссылается на 3 первичных ключа в 3 разных таблицах.Но когда я хочу вставить в него, я вижу сообщение об ошибке, в котором говорится, что родительский ключ не найден!что мне делать?
CREATE TABLE A
( X char(11) not null,
id char(11) not null,
PRIMARY KEY(X,id),
FOREIGN KEY(id) REFERENCES B(employee_id),
FOREIGN KEY(id) REFERENCES C(customer_id)
);
Комментарии:
1. вставили ли вы данные в свои таблицы B и C, соответствующие вашему
id
значению в таблице A?2. Что-то не так с дизайном. Одно поле таблицы, ссылающееся на три разные таблицы, требующее наличия одного и того же значения в трех таблицах в качестве первичного ключа.
3. Cybernate прав. Не имеет смысла пытаться использовать один внешний ключ для значений pkey в двух разных таблицах. Я удивлен, что Oracle вообще разрешила создавать эти ограничения.
4. да, я сделал. Я сделаю так, как сказал Джастин в своем ответе, спасибо.
Ответ №1:
Если вы хотите, чтобы ID
столбец в A был либо внешним ключом к EMPLOYEE_ID
столбцу в B, либо внешним ключом к CUSTOMER_ID
столбцу в C, у вас проблема — вы не можете объявить внешний ключ для этого отношения типа либо / или.
С точки зрения моделирования данных у вас есть несколько вариантов
- Вы можете создать два столбца в A,
EMPLOYEE_ID
столбец, который является обнуляемым внешним ключом кEMPLOYEE_ID
столбцу в B, иCUSTOMER_ID
столбец, который является обнуляемым внешним ключом кCUSTOMER_ID
столбцу в C. Затем вы можете создать ограничение проверки для A, чтобы точно один из этих двух столбцов был равен NULL. - Вы можете создать новую
ENTITY
таблицу, содержащую всеEMPLOYEE_ID
иCUSTOMER_ID
значения.EMPLOYEE_ID
в B был бы внешний ключ кENTITY_ID
столбцу вENTITY
, как иCUSTOMER_ID
столбец в C иENTITY_ID
столбец в A. - Вы можете оставить столбцы в A отдельно и исключить внешний ключ. Тогда вы были бы ответственны за проверку ссылочной целостности в вашем коде. Этот последний вариант, как правило, не является хорошей идеей.
Как правило, я бы также с большим подозрением относился к столбцам, объявленным как CHAR (11). В Oracle практически нет случая, когда действительно имело бы смысл использовать CHAR вместо VARCHAR2. В лучшем случае, это промывка.
Комментарии:
1. лично я бы выбрал второй вариант.
2. Но если я напишу так, как вы говорите, я не могу сказать, что 2 других имеют значение null, поскольку все они являются первичными ключами. Вы понимаете, что я имею в виду?
3. Первичный ключ, составной или нет, не может содержать nulls. По определению ключи не допускают нулевых значений. Oracle не разрешает значения null в столбцах, подверженных ограничению ПЕРВИЧНОГО КЛЮЧА.
4. @Dportas — Вы абсолютно правы. Я путал семантику для составных уникальных ограничений с составными ограничениями первичного ключа. Для ясности я удалю этот комментарий. Спасибо за исправление!
Ответ №2:
Ваш столбец id
в таблице A ссылается на столбец в таблице B, а также на столбец в таблице C. Если вам нужно вставить данные в таблицу A, значение в id
поле должно соответствовать значению в таблицах B и C, в противном случае вы нарушаете свое ограничение FK; невозможно вставить строку в таблицу A, содержащую столбец, ссылающийся на несуществующую строку в таблице B или C.
Ответ №3:
Создайте единственную родительскую таблицу (для примера я назову ее Party). Ссылайтесь на таблицу Party из всех трех таблиц A, B, C. В результате несколько внешних ключей будут заменены одним внешним ключом, ссылающимся на таблицу Party. Это пример шаблона обобщения / специализации, «подтипа», который вы найдете во многих книгах по моделированию данных.