ВНЕШНИЕ КЛЮЧИ, КОТОРЫЕ ССЫЛАЮТСЯ НА СВОИ ПОДЧИНЁННЫЕ ТАБЛИЦЫ
Как было упомянуто ранее, ограничение FOREIGN KEY может представить имя это в частной таблице, как таблице родительского ключа. Будучи далеко не простой, эта особенность может пригодиться.
Предположим, что мы имеем таблицу Employees с полем manager (администратор). Это поле содержит номера каждого из служащих, некоторые из которых являются ещё и администраторами. Но, так как каждый администратор одновременно является служащим, то он, естественно, будет также представлен и в этой таблице.
Давайте создадим таблицу, где номер служащего (столбец с именем empno), объявляется как первичный ключ, а администратор как внешний ключ будет ссылаться на нее:
CREATE TABLE Employees (empno integer NOT NULL PRIMARY KEY, name char(10) NOT NULL UNIOUE, manager integer REFERENCES Employees);
(Так как внешний ключ это ссылаемый первичный ключ таблицы, список столбцов может быть исключен.)
Имеется содержание этой таблицы:
EMPNO NAME MANAGER 1003 Terrence 2007 2007 Atali NULL 1688 McKenna 1003 2002 Collier 2007
Как вы видите, каждый из них (но не Atali) ссылается на другого служащего в таблице как на своего администратора. Atali, имеющий наивысший номер в таблице, должен иметь значение, установленное в NULL. Это дает другой принцип справочной целостности. Внешний ключ, который ссылается обратно на частную таблицу, должен позволять значения = NULL. Если это не так, то как бы вы могли вставить первую строку? Даже если эта первая строка ссылается на саму себя, значение родительского ключа должно уже быть установлено, когда вводится значение внешнего ключа. Этот принцип будет верен, даже если внешний ключ ссылается обратно к частной таблице не напрямую, а с помощью ссылки к другой таблице, которая затем ссылается обратно к таблице внешнего ключа.
Например, предположим, что наша таблица Продавцов имеет дополнительное поле, которое ссылается на таблицу Заказчиков так, что каждая таблица ссылается на другую, как показано в следующем операторе CREATE TABLE:
CREATE TABLE Salespeople (snum integer NOT NULL PRIMARY KEY, sname char(10) NOT NULL, city char(10), comm declmal, cnum integer REFERENCES Customers);
CREATE TABLE Customers ( cnum integer NOT NULL PRIMARY KEY, cname char(10) NOT NULL, city char(10), rating integer, snum integer REFERENCES Salespeople);
Это называется перекрестной ссылкой. SQL поддерживает это теоретически, но практически это может составить проблему. Любая таблица из этих двух, созданная первой, является ссылочной таблицей, которая ещё не существует для другой. В интересах обеспечения перекрестной ссылки, SQL фактически позволяет это, но никакая таблица не будет пригодна для использования, пока они обе находятся в процессе создания.
С другой стороны, если эти две таблицы создаются различными пользователями, проблема становится ещё более трудной. Перекрестна ссылка может стать полезным инструментом, но она не без неоднозначности и опасностей. Предшествующий пример не совсем пригоден для использования, потому что он ограничивает продавца одиночным заказчиком, и, кроме того, совсем не обязательно использовать перекрёстную ссылку, чтобы достичь этого.
Мы рекомендуем чтобы вы были осторожны в его использовании и анализировали, как ваши программы управляют эффектами модификации и удаления, а также процессами привилегий и диалоговой обработки запросов, перед тем как вы создаёте перекрестную систему справочной целостности. (Привилегии и диалоговая обработка запросов будут обсуждаться, соответственно, в Главах 22 и 23.)