База данных: Как различить отношения «один или более» и «ноль или более»? - PullRequest
12 голосов
/ 04 апреля 2011

Средства проектирования позволяют различать "один TO ноль или более " и "один TO один или более " отношения.Я мог бы представить, как реализовать отношение «один к нулю или более» :


CHILD_TABLE

(pk) chid_id
(fk) parent_id (обязательно)


PARENT_TABLE

(pk) parent_id


Как реализовать "один-к-одному или-подробнее " отношения?Как сказать, что родителю нужен хотя бы один ребенок?Или " один или более " обычно реализуется как " ноль или более "?

Ответы [ 6 ]

8 голосов
/ 04 апреля 2011

Очевидно, что принудительное выполнение ограничений, таких как указанное вами, потребует от клиентов иногда выдавать (и механизмы СУБД принимать) что-то, что может быть помечено как «одновременное обновление», то есть более чем одна отдельная таблица является обновляется перед проверкой любых ограничений.

Язык SQL (я имею в виду, стандарт) предлагает поддержку для этого через CREATE ASSERTION. Увы, ни один из существующих в настоящее время движков не поддерживает это утверждение.

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

Существуют системы, которые предлагают поддержку для применения ваших ограничений, но они не являются системами SQL.

Решение aioobe довольно оригинально, но имейте в виду, что вы можете сделать это только путем дублирования всех столбцов со стороны «много» (/ потомков) до стороны «один» (/ родитель) (потому что в противном случае у вас все еще есть та же проблема между двумя таблицами, за исключением того, что часть "или-больше" исчезла, но проблема не в этом). И если вы сделаете это, вы столкнетесь с большими трудностями, когда:

  • написание запросов со стороны «многие» (вы должны следить за тем, чтобы та другая строка, которая находится со стороны «одна», всегда получала UNIONed со стороной «много»),
  • принудительное использование ключей на стороне "много" (вам нужно убедиться, что ни один ключ на стороне "много" не будет иметь того же значения, что и тот другой ряд, который находится на стороне "один",
  • обеспечение ссылочной целостности, когда указанная таблица сама является вашей «одной или более» стороной (вы должны убедиться, что она также действительна для существования ссылок на эту другую строку, которая находится на стороне «один») .

Таким образом, решение aioobe, хотя и оригинальное, скорее всего, создаст больше новых проблем, чем решит.

6 голосов
/ 04 апреля 2011

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

Если вы оберните два оператора INSERT внутри транзакции, то вы гарантируете, что если дочерняя вставка завершится неудачно, родительская вставка будет отменена. Однако бизнес-логика должна гарантировать, что родитель не будет вставлен без дочернего элемента.

3 голосов
/ 04 апреля 2011

В SQL Server отношения внешнего ключа всегда от «один» до «ноль или более».Отношение «один» к «одному или нескольким» также очень затруднит вставку исходных данных.(вам нужно будет отключить внешний ключ, прежде чем вы сможете вставить запись в родительскую таблицу)

2 голосов
/ 04 апреля 2011

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

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

1 голос
/ 04 апреля 2011

Вы можете реализовать это как «один к одному» плюс «один к нулю или больше»

0 голосов
/ 04 апреля 2011

Язык SQL имеет очень ограниченную поддержку ссылочной целостности и ограничений целостности в целом.Стандартный SQL (и большинство, если не все популярные СУБД SQL) не поддерживает ограничения один к одному или более.Ограничения SQL FOREIGN KEY всегда являются необязательными для ссылочной стороны отношения.Инструменты и языки моделирования данных обычно поддерживают такие ограничения (ORM, ERD), но СУБД редко позволяют их реализовать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...