Описание ссылочной целостности Назад В начало Вперед

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

Ссылочная целостность также может быть задана при описании таблицы (см. "Оператор описания таблицы. ").

<описание-ссылочной-целостности> =
  alter table <имя-родительской-таблицы> [ <внешний-ключ> ]
  references
	( <описание-ссылки> )
  | (case {<описание-переключаемой-ссылки>})

<имя-родительской-таблицы> - имя таблицы, содержащей ссылку на другую таблицу.

<внешний-ключ> - конструкция, описывающая внешний ключ для связи таблиц. Внешний ключ задается индексом или явным перечислением полей.

<внешний-ключ> = foreign key <имя-индекса> | (<список-полей>)

<имя-индекса> - индекс родительской таблицы, задающий поля, по которым цепляется подчиненная таблица.

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

Ключевое слово references открывает секцию с описанием ссылки. Описание ссылки заключается в круглые скобки.

<описание-ссылки> -

<описание-ссылки> =
  [ table | objref ] <подчиненная-таблица-или-объект>
  [ primary key <имя-индекса> ]
  [ restrict [ set null [ = <значение> ]]]

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

<описание-переключаемой-ссылки> - отличается от описания простой ссылки тем, что имеет предложение when.

<описание-переключаемой-ссылки> =
  <подчиненная-таблица-или-объект>
  [ primary key <имя-индекса> ]
  (when <имя-поля-родительской-таблицы> = <значение>)
  [ restrict [ set null [ = <значение> ]]]

Опция table задает контроль ссылочной целостности по физической таблице. Опция доступна начиная с Атлантис 5.1.23.

Опция objref задает контроль ссылочной целостности по табличному объекту. Опция доступна начиная с Атлантис 5.1.23.

Если ни одна из опций table или objref не задана, то сначала ищется таблица, принадлежащая тому же компоненту, что и описываемая. Если таблица не найдена, ищется табличный враппер.

< подчиненная-таблица-или-объект> - описание ссылки начинается с указания имени подчиненной таблицы. Начиная с Атлантис 5.1.23 вместо имени таблицы можно указать имя табличного объекта (табличный враппер или переменная типа objInterface). В этом случае ссылочная целостность будет проверяться через указанный объект. О табличных объектах см. "Использование табличных объектов. ".

Конструкция primary key <имя-индекса> предназначена для описания первичного ключа подчиненной таблицы. По умолчанию берется суррогатный ключ.

Ключевое слово restrict является признаком ограничивающей ссылочной целостности. Ограничивающая ссылочная целостность накладывает ограничения на операции модификации связанных таблиц, не позволяя производить недопустимые операции. Если признак отсутствует, то ссылочная целостность является просто описательной, но не ограничивающей.

Например, пусть существуют 2 таблицы: таблица отделов предприятия и таблица сотрудников. Каждый сотрудник работает в определенном отделе. Таким образом, рассматриваемые таблицы связаны между собой. Если в таблице отделов есть поле - номер отдела и в таблице сотрудников определен номер отдела, где работает этот сотрудник, то можно описать ссылочную целостность для этих двух таблиц. Описательная ссылочная целостность просто опишет взаимосвязь, не накладывая никаких ограничений на операции модификации связанных таблиц. Ограничивающая ссылочная целостность не позволит произвести операции, нарушающие заданные отношения. Например, нельзя в таблицу сотрудников вставить запись с номером отдела, не существующим в таблице отделов.

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

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

Конструкция set null [= <значение>] предназначена для описания нулевых ссылок.

Система Атлантис позволяет пользователю устанавливать значение нуля для нулевой ссылки (по умолчанию - нуль или пустая строка в зависимости от типа индекса). Например, нулевая ссылка может обозначаться числом 666:

set null = 666

Конструкция when определяет условие, при выполнении которого осуществляется данная подцепка.

<имя-поля-родительской-таблицы> - поле родительской таблицы, используемое как переключатель.

<значение> - значение поля, при котором используется данная ссылка (таблица+индекс).

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

[system]
CalcObjRelOptimization=on

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

Другими словами, оптимизированные ссылки будут проверяться и при обращении к таблице через объект (потому что объект замыкается на таблицу) и при обращении к таблице напрямую изнутри компонента. А неоптимизированные ссылки будут проверяться только при обращении через табличный объект. Практически это означает, что неоптимизированные ссылки будут проверяться только при обращении из другого компонента, потому что вряд ли внутри компонента все работают через объект и не обращаются к таблице напрямую.

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

Пример

Создадим базу данных:

create dictionary RelationTest using "dict" with replace;
 create table Root1 "Корень 1"
  using "%DATA%data\aaa\Root1.dat"
  with tableOptions header
   (
	 fw1	 : word,
	 fs1	 : string[40],
	 fw2	 : word,
	 fs2	 : string[20],
	 comment : string
   )
   with index (
	iw1 = fw1 (unique),
	is1 = fs1 (unique),
	iw2 = fw2 (unique),
	is2 = fs2
   );
 create table Root2 "Корень 2"
  using "%DATA%data\aaa\Root2.dat"
  with tableOptions header
   (
	 fw1	 : word,
	 fs1	 : string[40],
	 fw2	 : word,
	 fs2	 : string[20],
	 comment : string
   )
   with index (
	iw1 = fw1 (unique),
	is1 = fs1 (unique),
	iw2 = fw2 (unique),
	is2 = fs2
   );
 create table Leaf1 "Лист 1"
  using "%DATA%data\aaa\Leaf1.dat"
  with tableOptions header
   (
	 fw1		 : word,
	 fs1		 : string[40],
	 fw2		 : word,
	 fs2		 : string[20],
	 switch	: word,
	 root1_Nrec  : comp,
	 comment	 : string
   )
   with index (
	iw1 = fw1,
	is1 = fs1,
	iw2 = fw2,
	is2 = fs2,
	iRoot1_Nrec = root1_Nrec
   );
 create table Leaf2 "Лист 2"
  using "%DATA%data\aaa\Leaf2.dat"
  with tableOptions header
   (
	 fw1		 : word,
	 fs1		 : string[40],
	 fw2		 : word,
	 fs2		 : string[20],
	 switch	: word,
	 fRoot1_NRec : comp,
	 comment	 : string
   )
   with index (
	iw1 = fw1,
	is1 = fs1,
	iw2 = fw2,
	is2 = fs2,
	iRoot1_Nrec = fRoot1_Nrec 
   );

Пример ограничивающей ссылочной целостности для описанной выше БД. Допустимы нулевые ссылки. Принимается значение нуля по умолчанию. Таблица Root1 ссылается на таблицу Root2. Первичный ключ is1 из таблицы Root2. Вторичный ключ - is1 из таблицы Root1:

alter table Root1
   foreign key is1
   references Root2
   primary key is1
   restrict
   set null;

Пример ограничивающей ссылочной целостности, нулевые ссылки не поддерживаются:

 alter table Leaf1
   foreign key iw1
   references Root1
   primary key iw1
   restrict;

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

 alter table Leaf1
   foreign key iRoot1_Nrec
   references Root1
   restrict;

Пример переключаемой ссылочной целостности. Таблица Leaf1 ссылается на Root1, если поле switch равно 1, и на Root2, если switch=2. При всех остальных значения switch ссылочная целостность не определена:

  alter table Leaf1
   foreign key iw2
   references
   case
	Root1  primary key iw2 (when switch=1) restrict,
	Root2  primary key iw2 (when switch=2) restrict;

Пример описательной ссылочной целостности:

  alter table Leaf1
   foreign key is1
   references Root1
   primary key is1;

Пример ограничивающей ссылочной целостности с установкой значения нуля пользователем:

alter table Leaf2
   foreign key iw1
   references
   Root2 primary key iw1
   Restrict
   set null = 600+60+6;

Пример ограничивающей ссылочной целостности с установкой значения нуля пользователем. Кроме того, показана комбинация описательной и ограничивающей ссылочной целостности при использовании переключателя:

  alter table Leaf2
   foreign key is1
   references
   case
	Root1  primary key is1 (when switch = 1)
	 restrict set null = 'Brave'+' heart',
	Root2  primary key is1 (when switch = 2);

Версия

Начиная с Атлантис 5.1.23 при описании ссылочной целостности наряду с таблицами можно использовать табличные объекты. Добавлены ключевые слова table и objref.