Ссылочная целостность

Поделись знанием:
Перейти к: навигация, поиск
К:Википедия:Статьи без источников (тип: не указан)

Ссы́лочная це́лостность (англ. referential integrity) — необходимое качество реляционной базы данных, заключающееся в отсутствии в любом её отношении внешних ключей, ссылающихся на несуществующие кортежи.





Определение

Связи между данными, хранимыми в разных отношениях, в реляционной БД устанавливаются с помощью использования внешних ключей — для установления связи между кортежем из отношения A с определённым кортежем отношения B в предусмотренные для этого атрибуты кортежа отношения A записывается значение первичного ключа (а в общем случае значение потенциального ключа) целевого кортежа отношения B. Таким образом, всегда имеется возможность выполнить две операции:

  • определить, с каким кортежем в отношении B связан определённый кортеж отношения A;
  • найти все кортежи отношения A, имеющие связи с определённым кортежем отношения B.

Благодаря наличию связей в реляционной БД можно хранить факты без избыточного дублирования, то есть в нормализованном виде. Ссылочная целостность может быть проиллюстрирована следующим образом:

Дана пара отношений A и B, связанных внешним ключом. Первичный ключ отношения B — атрибут B.key. Внешний ключ отношения A, ссылающийся на B — атрибут A.b. Ссылочная целостность для пары отношений A и B имеет место тогда, когда выполняется условие: для каждого кортежа отношения A существует соответствующий кортеж отношения B, то есть кортеж, у которого (B.key = A.b).

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

Если вышеприведённое условие не выполняется, говорят, что в базе данных нарушена ссылочная целостность. Такая БД не может нормально эксплуатироваться, так как в ней разорваны логические связи между зависимыми друг от друга фактами. Непосредственным результатом нарушения ссылочной целостности становится то, что корректным запросом не всегда удаётся получить корректный результат.

Пример

Так, в примере реляционная БД, состоящая из таблиц Address и Street, обеспечивает хранение адресов. При этом основная таблица, — Address, — содержит непосредственно номер дома и квартиры, а вместо имени улицы в поле Street имеет внешний ключ, ссылающийся на таблицу Street — справочник улиц. Очевидно, что полноценный адрес должен быть представлен двумя связанными записями в обеих названных таблицах, что технически выражается в условии: для любой записи таблицы Address в таблице Street должна существовать соответствующая запись, то есть запись со (Street.Key = Address.Street). Чтобы получить список полных адресов из таблиц такой структуры, когда в них соблюдается ссылочная целостность, достаточно применить к данным таблицам SQL-запрос:

 select * 
 from Address, Street
 where
   Address.Street = Street.Key

В данном примере, однако, ссылочная целостность нарушена. Две записи таблицы Address (Key = 887 и Key = 994) имеют в поле Street так называемые «висящие» ссылки — значения, которым не соответствуют записи в таблице Street (эти ссылки показаны красным цветом). Из-за этого результат вышеприведённого запроса не будет содержать этих двух записей — для них условие запроса не выполнится. И ещё одна запись не будет выбрана вышеприведённым запросом — запись таблицы Address с (Key = 85). Это вариант намеренного (и, в некоторых случаях, легального) нарушения ссылочной целостности — в поле внешнего ключа записан NULL (показано голубым цветом). Чтобы получить список всех адресов, даже тех, у которых не указана улица, необходимо использовать открытое соединение, в одном из вариантов синтаксиса записываемое так:

 select * 
 from Address left outer join Street on (Address.Street = Street.Key)

Если же требуется получить список, не включающий записи с «висящими» ссылками, то придётся усложнить запрос:

 select *  
 from Address left outer join Street on ((Address.Street = Street.Key) or (Address.Street is null))

Поддержание ссылочной целостности в БД

Причины нарушений

Правильно спроектированная и поддерживаемая база данных не допускает возможности нарушения ссылочной целостности. Тем не менее, такие нарушения могут появиться в ходе эксплуатации базы по целому ряду причин. Некоторые из них:

  • Некорректная работа прикладного программного обеспечения. Понятно, что при ошибке в программе, выполняющей модификацию базы данных, база может быть модифицирована недопустимым образом, в результате чего образуются «висящие» ссылки. Программа может совершать ошибки следующих видов:
    • Неполная запись объектов. Данные объекта размещаются в записях нескольких таблиц, а программа не записывает какую-то из них.
    • Некорректная правка ссылки. Значение внешнего ключа изменяется на такое, которому не соответствует ни одна запись в связанной таблице.
    • Правка первичного ключа без каскадного обновления. В таблице, на которую есть ссылки, правится первичный ключ, но при этом внешние ключи в связанных с ней таблицах остаются без изменения.
    • Удаление записи без каскадного обновления. Из таблицы удаляется запись, на которую имеются ссылки по внешним ключам других таблиц, при этом в связанных записях внешние ключи не меняются. В результате все ссылающиеся на неё записи других таблиц становятся некорректными.
  • Сбои в работе системного программного обеспечения и оборудования. Даже когда прикладное программное обеспечение работает совершенно правильно, возможно нарушение ссылочной целостности. Например, если при добавлении объекта в базу нужно добавить несколько связанных записей в несколько таблиц, очевидно, что ссылочная целостность будет нарушена в процессе добавления данных (когда часть связанных записей уже добавлена, а часть — ещё нет), и восстановится только после завершения операции. Если во время выполнения операции она будет прервана (из-за переполнения диска, сбоя питания, или по каким-то другим причинам), часть записей будет добавлена в БД, часть — нет. Часть добавленных записей останется с некорректными ссылками.

Пустые внешние ключи

Возможна ситуация, когда внешний ключ вместо ссылки на существующую запись в таблице БД содержит «отсутствующее значение» NULL. Такое положение можно трактовать как отсутствие какой-то части объекта. Хотя с точки зрения чистой теории это недопустимо, на практике иногда бывает удобно разрешить использование пустых внешних ключей. Чтобы корректно работать с группами связанных таблиц, допускающих пустые внешние ключи, используется специфическая операция языка SQLоткрытое соединение (другое название — «внешнее соединение», англ. outer join).

Ссылочная целостность на триггерах

Возможно поддержание ссылочной целостности БД с использованием механизма триггеров. В этом случае для любой потенциально опасной операции над таблицей создаётся триггер, который производит необходимые проверки или даже изменяет данные в связанных таблицах, чтобы исключить потерю ссылок.

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

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

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

Ссылочная целостность на внешних ключах

СУБД может иметь механизм автоматического поддержания ссылочной целостности, основанный на явном описании ссылок при создании БД. При описании таблиц БД программист явно описывает, какие поля таблиц являются внешними ключами и на какие таблицы они ссылаются. Эта информация сохраняется в служебных областях памяти БД. Любая операция, изменяющая данные в таблице, вызывает автоматическую проверку ссылочной целостности. При этом:

  • При операции добавления или редактирования записи автоматически проверяется, ссылаются ли внешние ключи в этой записи на существующие записи в заявленных при описании связанных таблицах. Если выясняется, что операция приведёт к появлению некорректных ссылок, она не выполняется — система возвращает ошибку.
  • При операции редактирования записи проверяется:
    • если изменяется её первичный ключ и на данную запись имеются ссылки, то операция редактирования завершается с ошибкой;
    • если изменяется какой-то из внешних ключей, хранящихся в этой записи, и после изменения внешний ключ будет ссылаться на несуществующую запись, то операция редактирования завершается с ошибкой.
  • При операции удаления записи проверяется, нет ли на неё ссылок. Если ссылки имеются, то возможно три варианта дальнейших действий (фактически выполняемый зависит от СУБД и от выбора программиста, который он должен сделать при описании связи):
    • Запрет — удаление блокируется и возвращается ошибка.
    • Каскадное удаление — в одной транзакции производится удаление данной записи и всех записей, ссылающихся на данную. Если на удаляемые записи также есть ссылки и настройки также требуют удаления, то каскадное удаление продолжается дальше. Таким образом, после удаления данной записи в базе не остаётся ни одной записи, прямо или косвенно ссылающейся на неё. Если хотя бы одну из ссылающихся записей удалить не получается (либо для неё настроен запрет, либо происходит какая-либо ещё ошибка), то все удаления запрещаются.
    • Присвоение NULL — во все внешние ключи записей, ссылающихся на данную, записывается маркер NULL. Если хотя бы для одной из ссылающихся записей это невозможно (например, если поле внешнего ключа описано как NOT NULL), то удаление запрещается.

Напишите отзыв о статье "Ссылочная целостность"

Ссылки

Отрывок, характеризующий Ссылочная целостность

Moscou, la capitale asiatique de ce grand empire, la ville sacree des peuples d'Alexandre, Moscou avec ses innombrables eglises en forme de pagodes chinoises! [Москва, азиатская столица этой великой империи, священный город народов Александра, Москва с своими бесчисленными церквами, в форме китайских пагод!] Эта Moscou не давала покоя воображению Наполеона. На переходе из Вязьмы к Цареву Займищу Наполеон верхом ехал на своем соловом энглизированном иноходчике, сопутствуемый гвардией, караулом, пажами и адъютантами. Начальник штаба Бертье отстал для того, чтобы допросить взятого кавалерией русского пленного. Он галопом, сопутствуемый переводчиком Lelorgne d'Ideville, догнал Наполеона и с веселым лицом остановил лошадь.
– Eh bien? [Ну?] – сказал Наполеон.
– Un cosaque de Platow [Платовский казак.] говорит, что корпус Платова соединяется с большой армией, что Кутузов назначен главнокомандующим. Tres intelligent et bavard! [Очень умный и болтун!]
Наполеон улыбнулся, велел дать этому казаку лошадь и привести его к себе. Он сам желал поговорить с ним. Несколько адъютантов поскакало, и через час крепостной человек Денисова, уступленный им Ростову, Лаврушка, в денщицкой куртке на французском кавалерийском седле, с плутовским и пьяным, веселым лицом подъехал к Наполеону. Наполеон велел ему ехать рядом с собой и начал спрашивать:
– Вы казак?
– Казак с, ваше благородие.
«Le cosaque ignorant la compagnie dans laquelle il se trouvait, car la simplicite de Napoleon n'avait rien qui put reveler a une imagination orientale la presence d'un souverain, s'entretint avec la plus extreme familiarite des affaires de la guerre actuelle», [Казак, не зная того общества, в котором он находился, потому что простота Наполеона не имела ничего такого, что бы могло открыть для восточного воображения присутствие государя, разговаривал с чрезвычайной фамильярностью об обстоятельствах настоящей войны.] – говорит Тьер, рассказывая этот эпизод. Действительно, Лаврушка, напившийся пьяным и оставивший барина без обеда, был высечен накануне и отправлен в деревню за курами, где он увлекся мародерством и был взят в плен французами. Лаврушка был один из тех грубых, наглых лакеев, видавших всякие виды, которые считают долгом все делать с подлостью и хитростью, которые готовы сослужить всякую службу своему барину и которые хитро угадывают барские дурные мысли, в особенности тщеславие и мелочность.
Попав в общество Наполеона, которого личность он очень хорошо и легко признал. Лаврушка нисколько не смутился и только старался от всей души заслужить новым господам.
Он очень хорошо знал, что это сам Наполеон, и присутствие Наполеона не могло смутить его больше, чем присутствие Ростова или вахмистра с розгами, потому что не было ничего у него, чего бы не мог лишить его ни вахмистр, ни Наполеон.
Он врал все, что толковалось между денщиками. Многое из этого была правда. Но когда Наполеон спросил его, как же думают русские, победят они Бонапарта или нет, Лаврушка прищурился и задумался.
Он увидал тут тонкую хитрость, как всегда во всем видят хитрость люди, подобные Лаврушке, насупился и помолчал.
– Оно значит: коли быть сраженью, – сказал он задумчиво, – и в скорости, так это так точно. Ну, а коли пройдет три дня апосля того самого числа, тогда, значит, это самое сражение в оттяжку пойдет.
Наполеону перевели это так: «Si la bataille est donnee avant trois jours, les Francais la gagneraient, mais que si elle serait donnee plus tard, Dieu seul sait ce qui en arrivrait», [«Ежели сражение произойдет прежде трех дней, то французы выиграют его, но ежели после трех дней, то бог знает что случится».] – улыбаясь передал Lelorgne d'Ideville. Наполеон не улыбнулся, хотя он, видимо, был в самом веселом расположении духа, и велел повторить себе эти слова.
Лаврушка заметил это и, чтобы развеселить его, сказал, притворяясь, что не знает, кто он.
– Знаем, у вас есть Бонапарт, он всех в мире побил, ну да об нас другая статья… – сказал он, сам не зная, как и отчего под конец проскочил в его словах хвастливый патриотизм. Переводчик передал эти слова Наполеону без окончания, и Бонапарт улыбнулся. «Le jeune Cosaque fit sourire son puissant interlocuteur», [Молодой казак заставил улыбнуться своего могущественного собеседника.] – говорит Тьер. Проехав несколько шагов молча, Наполеон обратился к Бертье и сказал, что он хочет испытать действие, которое произведет sur cet enfant du Don [на это дитя Дона] известие о том, что тот человек, с которым говорит этот enfant du Don, есть сам император, тот самый император, который написал на пирамидах бессмертно победоносное имя.
Известие было передано.
Лаврушка (поняв, что это делалось, чтобы озадачить его, и что Наполеон думает, что он испугается), чтобы угодить новым господам, тотчас же притворился изумленным, ошеломленным, выпучил глаза и сделал такое же лицо, которое ему привычно было, когда его водили сечь. «A peine l'interprete de Napoleon, – говорит Тьер, – avait il parle, que le Cosaque, saisi d'une sorte d'ebahissement, no profera plus une parole et marcha les yeux constamment attaches sur ce conquerant, dont le nom avait penetre jusqu'a lui, a travers les steppes de l'Orient. Toute sa loquacite s'etait subitement arretee, pour faire place a un sentiment d'admiration naive et silencieuse. Napoleon, apres l'avoir recompense, lui fit donner la liberte, comme a un oiseau qu'on rend aux champs qui l'ont vu naitre». [Едва переводчик Наполеона сказал это казаку, как казак, охваченный каким то остолбенением, не произнес более ни одного слова и продолжал ехать, не спуская глаз с завоевателя, имя которого достигло до него через восточные степи. Вся его разговорчивость вдруг прекратилась и заменилась наивным и молчаливым чувством восторга. Наполеон, наградив казака, приказал дать ему свободу, как птице, которую возвращают ее родным полям.]
Наполеон поехал дальше, мечтая о той Moscou, которая так занимала его воображение, a l'oiseau qu'on rendit aux champs qui l'on vu naitre [птица, возвращенная родным полям] поскакал на аванпосты, придумывая вперед все то, чего не было и что он будет рассказывать у своих. Того же, что действительно с ним было, он не хотел рассказывать именно потому, что это казалось ему недостойным рассказа. Он выехал к казакам, расспросил, где был полк, состоявший в отряде Платова, и к вечеру же нашел своего барина Николая Ростова, стоявшего в Янкове и только что севшего верхом, чтобы с Ильиным сделать прогулку по окрестным деревням. Он дал другую лошадь Лаврушке и взял его с собой.


Княжна Марья не была в Москве и вне опасности, как думал князь Андрей.
После возвращения Алпатыча из Смоленска старый князь как бы вдруг опомнился от сна. Он велел собрать из деревень ополченцев, вооружить их и написал главнокомандующему письмо, в котором извещал его о принятом им намерении оставаться в Лысых Горах до последней крайности, защищаться, предоставляя на его усмотрение принять или не принять меры для защиты Лысых Гор, в которых будет взят в плен или убит один из старейших русских генералов, и объявил домашним, что он остается в Лысых Горах.
Но, оставаясь сам в Лысых Горах, князь распорядился об отправке княжны и Десаля с маленьким князем в Богучарово и оттуда в Москву. Княжна Марья, испуганная лихорадочной, бессонной деятельностью отца, заменившей его прежнюю опущенность, не могла решиться оставить его одного и в первый раз в жизни позволила себе не повиноваться ему. Она отказалась ехать, и на нее обрушилась страшная гроза гнева князя. Он напомнил ей все, в чем он был несправедлив против нее. Стараясь обвинить ее, он сказал ей, что она измучила его, что она поссорила его с сыном, имела против него гадкие подозрения, что она задачей своей жизни поставила отравлять его жизнь, и выгнал ее из своего кабинета, сказав ей, что, ежели она не уедет, ему все равно. Он сказал, что знать не хочет о ее существовании, но вперед предупреждает ее, чтобы она не смела попадаться ему на глаза. То, что он, вопреки опасений княжны Марьи, не велел насильно увезти ее, а только не приказал ей показываться на глаза, обрадовало княжну Марью. Она знала, что это доказывало то, что в самой тайне души своей он был рад, что она оставалась дома и не уехала.
На другой день после отъезда Николушки старый князь утром оделся в полный мундир и собрался ехать главнокомандующему. Коляска уже была подана. Княжна Марья видела, как он, в мундире и всех орденах, вышел из дома и пошел в сад сделать смотр вооруженным мужикам и дворовым. Княжна Марья свдела у окна, прислушивалась к его голосу, раздававшемуся из сада. Вдруг из аллеи выбежало несколько людей с испуганными лицами.
Княжна Марья выбежала на крыльцо, на цветочную дорожку и в аллею. Навстречу ей подвигалась большая толпа ополченцев и дворовых, и в середине этой толпы несколько людей под руки волокли маленького старичка в мундире и орденах. Княжна Марья подбежала к нему и, в игре мелкими кругами падавшего света, сквозь тень липовой аллеи, не могла дать себе отчета в том, какая перемена произошла в его лице. Одно, что она увидала, было то, что прежнее строгое и решительное выражение его лица заменилось выражением робости и покорности. Увидав дочь, он зашевелил бессильными губами и захрипел. Нельзя было понять, чего он хотел. Его подняли на руки, отнесли в кабинет и положили на тот диван, которого он так боялся последнее время.