Заголовок в значительной степени говорит о том, что мне нужно, но я хочу посмотреть, как я могу взять два ограничения внешнего ключа из таблицы и два ограничения проверки и связать одно ограничение проверки, а второе ограничение проверки со вторым ограничением внешнего ключа.
Например, у меня есть две таблицы по 3: item
, action
, risk
. Item
ссылки action
или risk
от itemid
только мне нужны условные ссылки на более чем один внешний ключ, при этом каждый внешний ключ имеет одно уникальное ограничение проверки.
Я буду использовать тип элемента ('Действие' или «Риск») в своем проверочном ограничении, чтобы определить, на какую таблицу я ссылаюсь.
Вот моя команда:
ALTER TABLE `projectaim`.`items`
ADD CONSTRAINT `fk_item_risk` FOREIGN KEY (`ItemID`) REFERENCES `projectaim`.`risks`(`RiskID`)
ADD CONSTRAINT ck_item_type CHECK (itemtype = 'Risk')
Возможно ли это вообще в MySQL?
Упс, это уже не так, 8.0.16 их добавляет.
Я ценю комментарий, я пришел к выводу, что мне может понадобиться хранимая процедура.
Однако проверочные ограничения имеют ряд ограничений. Вы не можете выполнить в них подзапрос, поэтому это предотвращает использование CHECK
для проверки внешнего ключа. Невозможно сделать внешние ключи условными.
Поэтому используйте триггер или хранимую процедуру.
Похоже, вы пытаетесь реализовать полиморфные ассоциации, где данный столбец может быть идентификатором, ссылающимся на любую из нескольких родительских таблиц.
Ограничение внешнего ключа ссылается на одну родительскую таблицу. Вы не можете сделать их условными. Вот почему полиморфные ассоциации принципиально несовместимы с реляционными ограничениями.
Если вам нужно сослаться на одну из нескольких родительских таблиц, один из способов сделать это — создать несколько столбцов, каждый из которых допускает значение NULL. Затем вы можете использовать проверочное ограничение или триггер, чтобы убедиться, что ровно один из них не равен нулю.
CREATE TABLE items (
Itemid INT NOT NULL PRIMARY KEY,
Itemtype ENUM ('Action', 'Risk') NOT NULL,
Actionid INT NULL,
Riskid INT NULL,
FOREIGN KEY (Actionid) REFERENCES actions (Actionid),
FOREIGN KEY (Riskid) REFERENCES risks (riskid),
CHECK (CASE Itemtype
WHEN 'Action' THEN Actionid IS NOT NULL AND Riskid IS NULL
WHEN 'Risk' THEN Riskid IS NOT NULL AND Actionid IS NULL
END)
);
Смотрите также:
Спасибо или разъяснение фактического метода, по имени, я ориентируюсь здесь.
Привет, хорошо ли иметь два внешних ключа, один из которых может быть нулевым?
@Arash, в решении, которое я показываю здесь, оба внешних ключа должны допускать нули. Но в данной строке одно должно быть нулевым, а другое ненулевым.
Спасибо, @Билл. Извините, я не силен в английском; Я плохо задавал вопросы. Я имел в виду в один ряд. Это хорошая практика или я должен изменить дизайн своих таблиц?
@ Араш, полиморфные ассоциации сложны, и невозможно сказать, что одно решение подходит для всех случаев. Вы должны оценить различные решения и выбрать то, которое подходит для вашего проекта. Я не знаю вашего проекта, поэтому не могу сказать, какой из них лучше.
MySQL вообще не реализует ограничения
CHECK
.