Нарушение ссылочной целостности: что бы сказал Эдгар Кодд?
Я пытаюсь понять правила реляционной модели, как они были определены Эдгаром Коддом в 1970 году.
Особенно меня интересует, является ли ссылочная целостность частью его реляционной модели или нет. Я попытаюсь продемонстрировать на следующем примере (просто, чтобы сделать этот вопрос довольно):
Клиенты
+------+------------
| Name | Address
|------+------------
| John | ....
| Mike | ....
| Kate | ....
+------+------------
Счета - фактуры
+------+------------
| ID | Customer
|------+------------
| 1 | John
| 2 | John
| 3 | Mary
+------+------------
Теперь, как вы можете видеть, у нас есть один счет-фактура, где клиент (внешний ключ) - Мэри. Будет ли это нарушать его реляционную модель? Эдгар Кодд посмотрел бы на это и сказал бы, чёрт возьми, какого черта? Или он сказал бы, что это прекрасно...
Это теоретический вопрос.
6 ответов
Чтобы язык считался реляционно полным (фраза, придуманная Коддом), он должен поддерживать набор реляционных операторов, известных как реляционная алгебра. Заметьте, что не существует единственной истинной реляционной алгебры: Кодд предложил первую, но с тех пор другие усовершенствовали и основались на Кодде (например, Третий Манифест), и я уверен, что он увидит это как правильное и правильное.
Ссылочная целостность не является реляционным оператором и, следовательно, не является требованием для реляционной полноты языка. Является ли ограничение ссылочной целостности полезной или необходимой функцией СУБД, это другой вопрос.
Если в таблице Customers нет клиента с именем Mary, то между таблицами нет ссылочной целостности. В частности, внешний ключ относится к несуществующему первичному ключу.
Это нарушает реляционную модель? Нет. Он определен в реляционной модели (т.е. отсутствие ссылочной целостности) и является признаком того, что существует проблема с базовыми данными.
Из "Реляционной модели данных для крупных общих банков данных" Эдгара Кодда (из сообщений ACM, том 13, номер 6, июнь 1970 года):
Это может быть случай, когда пользователь намеревается вставить какой-то другой элемент в P - элемент, вставка которого преобразует согласованное состояние в согласованное состояние. Дело в том, что система обычно не может решить этот вопрос без опроса своего окружения (возможно, пользователя, который создал несоответствие).
Таким образом, предполагается, что будут проблемы ссылочной целостности и что их нужно будет решать пользователю или системе с помощью какого-либо программного метода.
Я прочитал следующее как четко заявляющее, что ссылочная целостность включена в реляционную модель:
Два правила целостности применяются к каждой реляционной базе данных:
1 целостность объекта:
Никакая метка любого типа не допускается ни в одном атрибуте, который является компонентом первичного ключа базового отношения2 Ссылочная целостность:
Пусть D будет доменом, из которого один или несколько первичных ключей с одним атрибутом получают свои значения. Пусть K будет внешним ключом, который извлекает свои значения из домена D. Каждое немаркированное значение, которое встречается в K, должно также существовать в базе данных как значение в первичном ключе некоторого базового отношения.
" Отсутствующая информация (применимо и неприменимо) в реляционных базах данных", EF Codd, ACM SIGMOD Record, vol. 15, нет 4, с. 53-78, 1986.
Под "знаком любого типа" он ссылается на неизвестное значение, для которого мы сегодня используем NULL. В этом документе предложены два разных типа неизвестных значений: одно для "применимо, но отсутствует", а другое для "неприменимо".
Под "неотмеченным" он подразумевает не NULL.
Комментарий от @dportas: Действительно, вам даже не нужно, чтобы ссылочное отношение было пустым, чтобы сделать аргумент. Он может содержать несколько строк, но, поскольку нельзя сказать, что A-знак в K равен какому-либо значению, существующему в этом ссылочном отношении, невозможно сказать, что гипотетическое пропущенное значение удовлетворяет ограничению. Поэтому разрешение знака А должно стать актом веры, что после предоставления значения оно будет удовлетворять ограничению, поскольку в противном случае строка была бы недействительной с момента ее вставки, и нам пришлось бы поддерживать концепцию нарушение обратной силы, что бессмысленно.
Реляционная модель не требует, чтобы функции ссылочной целостности применялись к каждой реляционной базе данных - это было бы абсурдно, если бы такие ограничения не были релевантными или желательными. Подумайте о списке членов клуба, состоящем из имени, адреса и номера участника. Там не обязательно будет какое-либо использование для ограничений RI, но это все еще реляционная база данных, если данные хранятся в форме отношения.
Даже 13 правил Кодда не требуют, чтобы СУБД поддерживала возможность создавать ограничения RI. Просто внешние ключи настолько полезны, что ожидается, что большинство СУБД будут иметь их.
Сначала вы спросите, является ли RI частью RM:
является ли ссылочная целостность частью его реляционной модели или нет
Да. Из классики Кодда "Является ли ваша СУБД действительно реляционной?" Компьютерный мир, 14 октября 1985 года:
Однако жизненно важно помнить, что реляционная модель включает в себя три основные части: структурную часть, манипулятивную часть и часть целостности - факт, который часто и удобно забывать.
Правило 10: Ограничения целостности, характерные для конкретной базы реляционных данных, должны определяться в подъязыке реляционных данных и храниться в каталоге, а не в прикладных программах.
Но тогда вы перефразируете другой и неоднозначный вопрос:
у нас есть один счет, где клиент (внешний ключ) - Мэри. Будет ли это нарушать его реляционную модель?
Если вы имеете в виду: разрешает ли RM объявленный FK нарушаться, т.е. не останавливаться СУБД?
Нет. Это будет СУБД, которая позволяет вам объявлять ограничение FK, но не применяет его. Такая СУБД в этом отношении нереляционная.
Если вы имеете в виду: разрешает ли RM бизнес-правило, которое гласит, что Клиент Счета должен также отображаться в Имени клиентов (т.е. все действительные состояния базы данных аналогичны таковым, то есть существует ограничение FK от клиента Счета до Имени клиента), чтобы он не был объявлен в СУБД (например, через объявление FK)?
Да. Но это плохой дизайн, потому что он допускает некоторые недопустимые состояния.
Я думаю, что хорошо это или нет, зависит от вашего дизайна.
Счет должен содержать данные такими, какими они были на момент создания или отправки счета. Таким образом, могут потребоваться данные, относящиеся к данным клиента, но не напрямую к внешнему ключу, особенно если вы используете естественный ключ.
Например, предположим, что Мэри Джонс заказала что-то и ей выставили счет 31 мая 2010 года. 12 сентября 2010 года она изменила свое имя на Мэри Джонс-Смит и переехала на адрес своего мужа. Счет, являющийся изображением во времени, должен содержать имя Мэри Джонс и оригинальный адрес, на который он был отправлен. Лучше всего сохранить ссылку на текущего клиента и его информацию (поэтому я должен иметь идентификатор клиента в таблице клиентов при изменении имен и таблицу счетов FK of Customerid). Но хранить Мэри Джонс, когда Мэри Джонс больше не существует в таблице клиентов, - это не только нормально, необходимо отслеживать, что на самом деле произошло.
То же самое с продуктами и ценами и счетами. Вы не хотели бы, чтобы счет отражал цену сейчас, но процесс во время счета, даже если это не имеет прямого отношения к тому, что там сейчас. В этом случае таблица Product может быть скорее справочной таблицей, чем истинным родительским дочерним отношением. Если вы храните все данные о продукте в таблице сведений о счете-фактуре, вам не нужен внешний ключ для продуктов, он нужен только для поиска активных продуктов во время размещения заказа. На самом деле, номер модели прошлой накладной может больше не быть в таблице продуктов, если поставщик изменил ее или полностью отбросил продукт. Но вы не хотели бы потерять данные о том, какие из этих продуктов были куплены в прошлом.
С другой стороны, если отношение требует, чтобы данные оставались согласованными с текущими значениями, формальный внешний ключ является лучшим методом.