Sql, триггерная функция вместо простого ограничения - PullRequest
0 голосов
/ 09 июня 2018

Я готовлюсь к курсу «База данных», и у нас было это упражнение на примере экзамена, который выложил учитель, к сожалению, он не дал полной коррекции, а всего лишь несколько советов.У меня возникают проблемы с пониманием того, почему в приведенном ниже примере он говорит нам использовать функцию триггера вместо простого ограничения NOT NULL.

This is the exercise

Теперь я бы просто реализовал связь междуB и C вот так:

CREATE TABLE B (
  b1 int PRIMARY KEY,
  b2 varchar(255)
);

CREATE TABLE C (
  c1 varchar(255) PRIMARY KEY,
  c2 int
);

CREATE TABLE BtoC (
 b1 int REFERENCES B(b1) ON DELETE RESTRICT ON UPDATE CASCADE,
 c1 varchar(255) NOT NULL REFERENCES C(c1) ON DELETE RESTRICT ON UPDATE CASCADE,  -- This would ensure the same constraint, that C has to be at least once in the relation table?
 PRIMARY KEY(b1,c1)
);

Но он сказал нам, что для связи между таблицами B и C нам потребуется триггерная функция для удовлетворения кардинальности отношений, вот его слова:

"NOT NULL для NOTHING не будет иметь никакого эффекта (NOT NULL применяется только к существующим строкам, а не к несуществующим строкам), и это не будет гарантировать, что ограничение действует. Таким образом, NOT NULL не работает для отношениятаблицы, только для внешних ключей. "

Я не могу разобраться в его рассуждениях, может, кто-нибудь мне это объяснит?Я был бы очень признателен.

1 Ответ

0 голосов
/ 09 июня 2018

Ваша версия гарантирует, что любая запись в BtoC имеет действительную ссылку C. не гарантирует, что для каждого значения C имеется хотя бы одна строка в BtoC.Сложная часть здесь - это «1» в отношениях.

Это сложный вид отношений, которые я могу представить - я даже не знаю, стоит ли это делать в SQL.

Один из способов - выделить одно из значений.Например, если бы данные были людьми в домохозяйствах, выделенный человек мог быть «главой домохозяйства».Вам нужен один из них.Таким образом, вы можете реализовать это следующим образом:

CREATE TABLE C (
  c1 varchar(255) PRIMARY KEY,
  c2 int,
  b_special int not null references b(b1)
);

Это технически решает проблему, но контрольные значения B разбиты на две таблицы, а не на одну.

Если вы хотите специальный Bбыть в BtoC, тогда становится сложно.Вы можете сделать это с помощью обратной ссылки:

alter table c add constraint fk_c_b_special
    foreign key (b_special, c) references btoc(b1, c1);

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

Наиболее распространенные решения:

  • Снимите ограничение и дайте приложению вставить в обе таблицы.
  • Добавьте «специальный» столбец в C, но не проверяйте, что столбецфактически в BtoC (хотя код всегда будет вставлять его).
  • Добавить «специальный» столбец к C, а затем разрешить отношение 0-n для остальных столбцов.
  • Напишите триггер удаления для BtoC, который не позволяет удалить последний B для данного C.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...