2008 г.
Базы данных. Вводный курс
Сергей Кузнецов
Назад Содержание Вперёд
23.3. Типизированные таблицы
В предыдущем подразделе уже упоминалась возможность определения типизированных таблиц, основанных на некотором структурном типе. Далее мы приведем и поясним соответствующие синтаксические правила, введем понятие иерархии типизированных таблиц и связь этой иерархии с иерархией структурных типов, а также обсудим соотношение понятия строки типизированной таблицы с понятием объекта в ООБД.
23.3.1. Определение типизированной таблицы
С точки зрения синтаксиса оператор определения типизированной таблицы является частным случаем оператора создания базовой таблицы CREATE TABLE
, обсуждавшегося в лекции 16 (там мы не имели возможности рассматривать этот частный случай). Типизированные таблицы определяются в следующем синтаксисе:
typed_table_defintion ::= CREATE TABLE typed_table_name
OF UDT_name
[ UNDER typed_table_name ]
[ (typed_table_element_list) ]
Первой существенной особенностью оператора создания типизированной таблицы является обязательное наличие раздела OF
, в котором указывается имя ранее определенного структурного типа. Строки типизированной таблицы являются экземплярами ассоциированного с таблицей структурного типа.
Подтаблицы и супертаблицы
Далее, при определении типизированной таблицы можно объявить ее подтаблицей некоторой другой типизированной таблицы (имя супертаблицы указывается в разделе UNDER
). Таблица R'
является собственной подтаблицей супертаблицы R
, если R'
не совпадает с R
(в этом случае таблица R
является собственной супертаблицей подтаблицы R'
). Супертаблица должна быть ассоциирована со структурным типом, являющимся непосредственным супертипом202) определяемой подтаблицы. Каждый столбец указанной супертаблицы наследуется подтаблицей; наследуются и характеристики столбцов супертаблицы – значения по умолчанию, ограничения целостности и т. д. Эти столбцы называются унаследованными столбцами подтаблицы, и они соответствуют атрибутам UDT подтаблицы, унаследованным от UDT супертаблицы. Кроме того, подтаблица будет содержать по одному столбцу для каждого собственного атрибута ассоциированного структурного типа. Такие столбцы подтаблицы называются заново определенными.
Как это принято в SQL, столбцы типизированной таблицы имеют порядковые номера. При этом унаследованные столбцы нумеруются до заново определенных столбцов и имеют те же номера, которые имели столбцы супертаблицы.
Определение элементов типизированной таблицы
Заключительным компонентом определения типизированной таблицы является конструкция typed_table_element_list
, являющаяся обобщением конструкции table_element_list
, которая используется в определении обычной базовой таблицы (см. лекцию 16). Элемент списка элементов типизированной таблицы определяется следующим синтаксическим правилом:
type_table_element ::= table_constraint_definition
| self-referencing_column_specification
| column_options
Как видно из этого правила, в определении типизированной таблицы разрешается указывать табличные ограничения целостности. Если определяемая таблица является подтаблицей некоторой супертаблицы, то в ней не допускается определение ограничения первичного ключа (PRIMARY KEY
). Однако если определяется максимальная супертаблица, то в ее определении допускается спецификация PRIMARY KEY
(с указанием одного или нескольких столбцов) или спецификация ограничения UNIQUE
(с указанием одного или нескольких столбцов) в комбинации с указанием NOT NULL
. В определении типизированной таблицы могут также содержаться спецификации ссылочных ограничений целостности. Ссылки могут вести как на типизированную, так и на обычную таблицу.
«Самоссылающийся» (self-referencing) столбец специфицируется в следующем синтаксисе:
REF IS column_name { SYSTEM GENERATED
| USER GENERATED | DERIVED }
Эта спецификация не может входить в определение подтаблицы. Спецификация должна присутствовать в определении максимальной супертаблицы, и самоссылающийся столбец, определенный в максимальной супертаблице, наследуется любой ее подтаблицей. Семантика самоссылающихся столбцов обсуждается в следующем пункте.
Последней разновидностью элемента типизированной таблицы являются опции столбцов (column_options
). Опции столбца можно указывать только для заново определенных столбцов – для унаследованных столбцов это не допускается. Соответствующая конструкция имеет следующий синтаксис:
column_name WITH OPTIONS ::= scope_clause
|default_clause
|column_constraint_definition_list
|collate_clause
Раздел scope_clause
может входить в опции только заново определяемого столбца с типом REF
(подробности в следующем подразделе). Для заново определяемого столбца некоторого типа символьных строк можно указать раздел collate_clause
, чтобы задать желаемый порядок на соответствующем наборе символов. Если требуется указать значение столбца по умолчанию, отличное от значения по умолчанию соответствующего атрибута, ассоциированного с определяемой таблицей структурного типа, можно воспользоваться опцией default_clause
. Наконец, для заново определяемого столбца можно указать одно или несколько ограничений, включая проверочные ограничения (см. лекцию 16).
23.3.2. Ссылочные значения и REF-типы
Понятия ссылочных значений и ссылочных (REF
) типов являются, по существу, неразделимыми. В SQL:1999 ссылочный тип может использоваться в качестве типа данных столбцов обычных таблиц, атрибутов структурных типов, SQL-переменных и параметров – словом, везде, где можно использовать другие типы данных SQL. Значения местоположения ссылочного типа всегда являются ссылочными значениями строк типизированных таблиц (т. е. значениями самоссылающихся столбцов этих строк).
Для удобства повторим синтаксис спецификации ссылочного типа:
reference_type_specification ::= system_generated_representation
| user_defined_representation
| derived_representation
system_generated_representation :== REF IS SYSTEM GENERATED
user_defined_representation :== REF USING predefined_type
derived_representation ::= REF USING (commalist_of_attributes)
Механизмы генерации ссылочных значений
В SQL:1999 и SQL:2003 обеспечиваются три механизма назначения уникальных идентификаторов экземплярам структурных типов, ассоциированных с типизированными таблицами. Во всех типизированных таблицах, ассоциированных с данным структурным типом, должен использоваться один и тот же механизм. Предоставляются следующие альтернативы выбора ссылочных значений, которые могут являться:
- значениями некоторого встроенного типа SQL (
user_defined_representation
), которые должны генерироваться приложением каждый раз при сохранении экземпляра структурного типа как строки типизированной таблицы; - значениями, порождаемыми из одного или нескольких атрибутов структурного типа;
- значениями, автоматически генерируемыми системой.
Как отмечалось в разделе 23.2 Определяемые пользователями типы, при определении любого максимального структурного супертипа явно или неявно задается спецификация ссылочного типа. Спецификация ссылочного типа наследуется всеми подтипами этого супертипа. При определении типизированных таблиц необходимо указать соответствующую спецификацию самоссылающегося столбца (конечно, эта спецификация логически избыточна, и, по всей вероятности, в следующих версиях стандарта SQL это требование будет ослаблено). Хотя соотношение между альтернативами спецификации ссылочного типа и спецификации самоссылающегося столбца очевидно, приведем его явно (табл. 23.1).
Таблица 23.1. Спецификации ссылочного типа и самоссылающегося столбцаreference_type_specification | self-referencing_column |
REF USING predefined_type | USER GENERATED |
REF FROM commalist_of_attributes | DERIVED |
REF IS SYSTEM GENERATED SYSTEM | GENERATED |
Если для некоторого структурного типа выбран вариант пользовательской генерации ссылочных значений, то ответственность за поддержание уникальности таких значений лежит на пользователе. Конечно, ограничения PRIMARY KEY
или UNIQUE
, определенные на уровне максимальной супертаблицы семейства типизированных таблиц, могут гарантировать отсутствие в любой таблице этого семейства дублирующих ссылочных значений, но в SQL:1999 отсутствуют какие-либо средства, предотвращающие повторное использование ссылочных значений из удаленных строк в самоссылающихся столбцах новых строк.
Преобразование задаваемых пользователем ссылочных значений к ссылочному типу
В этом случае в определении структурного типа может присутствовать конструкция ref_cast_option
(вернее, она должна присутствовать в определении соответствующего максимального супертипа). Синтаксис этой конструкции приводился в предыдущем разделе, но для удобства мы его повторим здесь:
ref_cast_option ::= cast_to_ref
| cast_to_type
cast_to_ref ::= CAST ( SOURCE AS REF ) WITH identifier
cast_to_type ::= CAST ( REF AS SOURCE ) WITH identifier
Чтобы пояснить эту конструкцию, предположим, что в определении структурного типа указано REF USING INTEGER
. Тогда соответствующие приложения отвечают за то, чтобы обеспечить глобально уникальные целые значения самоссылающегося столбца во всех строках всех типизированных таблиц, ассоциированных с этим структурным типом. Но приложения обеспечивают значения целого типа, а типом данных самоссылающегося столбца является некоторый ссылочный тип.
Для решения именно этой проблемы и предназначена конструкция ref_сast_option
. В этой конструкции вводятся имена двух SQL-функций, первая из которых служит для преобразования ссылочных значений, обеспечиваемых приложением, к соответствующему REF
-типу при вставке или обновлении строк типизированной таблицы (SOURCE AS REF
). Вторая функция преобразует значения REF
-типа к соответствующему встроенному типу данных при выборке строк из типизированной таблицы (REF AS SOURCE
). Система автоматически генерирует обе подпрограммы, и конструкция ref_сast_option
позволяет лишь назначить подпрограммам имена. Если конструкция ref_сast_option
явно не включается в определение структурного типа с REF USING predefined_type
, то имена подпрограммам назначаются системой. Единственным преимуществом явного назначения имен является возможность явного вызова этих функций при написании SQL-операторов, содержащих выражения REF
-типа, которые нужно привести к соответствующему встроенному типу. Заметим, что такие функции невозможно написать вручную, поскольку правила отображения зависят от реализации SQL.
Если для структурного типа выбирается альтернатива порождения ссылочных значений, то система использует для порождения ссылочных значений значения неявно указанных столбцов (соответствующих явно указанным атрибутам ассоциированного структурного типа). При этом остаются все упомянутые выше проблемы, хотя в таком случае явно требуется объявление ограничений PRIMARY KEY
или UNIQUE
для соответствующего набора столбцов.
Наконец, при выборе последней альтернативы (системно-генерируемые ссылочные значения) каждой строке, вставляемой в типизированную таблицу, ассоциированную с соответствующим структурным типом, присваивается уникальный идентификатор. Это значение сохраняется в самоссылающемся столбце и может быть использовано любым приложением для уникальной идентификации данной строки на всем протяжении жизни таблицы.
Спецификация ссылочного типа при объявлении столбцов и атрибутов
Самоссылающиеся столбцы всегда имеют REF
-тип. Конкретный REF
-тип зависит от двух факторов:
- структурного типа, ассоциированного с типизированной таблицей:
REF
-тип всегда связан с некоторым структурным типом; - выбранного способа генерации ссылочных значений; эта информация задается в определении структурного типа и не присутствует в спецификации ссылочного типа.
Для объявления местоположения ссылочного типа используется следующий синтаксис:
reference_type ::= REF (referenced_type) [ SCOPE table_name ]
referenced_type ::= UDT_name
UDT_name
должно задавать имя типа (referenced_type
), на экземпляры которого будут указывать значения ссылочного типа. REF
-тип может использоваться в качестве типа атрибута структурного типа, и в этом случае referenced_type
может быть тем же самым, что и определяемый структурный тип. Во все остальных случаях referenced_type
должен являться некоторым существующим структурным типом.
В необязательном разделе SCOPE
задается имя типизированной таблицы. Ассоциированным структурным типом этой таблицы должен быть referenced_type REF
-типа, в спецификации которого содержится данный раздел SCOPE
. Хотя можно было бы ожидать, что значение REF
-типа можно использовать для ссылки на строки типизированных таблиц, ассоциированный структурный тип которых является собственным подтипом указанного referenced_type
, в SQL такая разновидность ссылок не допускается. Ассоциированный структурный тип таблицы, на строки которой указывают значения REF
-типа, должен быть в точности тем же, что и referenced_type
этого REF
-типа. Но, конечно, можно объявить REF
-тип, у которого referenced_type
является ассоциированным структурным типом подтаблицы, хотя самоссылающийся столбец этой подтаблицы необходимо наследуется от максимальной супертаблицы семейства таблиц.
Поддержка согласованности ссылок
Никакое ссылочное значение никогда не идентифицирует какую-либо строку, кроме той, с которой оно было ассоциировано с самого начала. Если эта строка удаляется, то значение ничего не идентифицирует и никогда не может быть связано с другой строкой. Из этого следует, что система должна каким-либо образом узнавать о том, идентифицирует ли данное ссылочное значение какую-то хранимую строку или ничего не идентифицирует (является висящей ссылкой). Но как система может это узнать, не потратив множество ресурсов? Отчасти здесь может помочь раздел SCOPE
. В этом разделе указывается одна таблица, в которой строки должны существовать для всех значений данного местоположения, типом данных которого является некоторый REF
-тип. (В будущих версиях стандарта SQL, по всей видимости, будет разрешено указывать в разделе SCOPE
список имен типизированных таблиц или даже использовать некоторую конструкцию, означающую «все таблицы, ассоциированные с данным структурным типом».)
Итак, если определяется столбец таблицы, поле строчного типа или атрибут структурного типа, и типом этого местоположения является REF
-тип, то можно специфицировать раздел SCOPE
. Однако если такой раздел действительно указывается, то требуется также указать, нужна ли проверка ссылочных значений. Для этого служит конструкция reference_scope_check
, определяемая следующим синтаксическим правилом:
reference_scope_check ::= REFERENCES ARE [ NOT ] CHECKED
[ ON DELETE referential_action ]
Если указывается REFERENCES ARE NOT CHECKED
или если раздел SCOPE
не задается, то в определяемом местоположении можно хранить любое ссылочное значение, независимо от того, является ли оно значением самоссылающегося столбца какой-либо таблицы, на строку которой предположительно указывает ссылка. В этом случае система не гарантирует, что ссылочное значение действительно указывает на строку (но, конечно, это значение должно быть значением правильного типа – REF
-типа указанного структурного типа).
Если же указывается REFERENCES ARE CHECKED
, то каждый раз при сохранении значения в определяемом столбце, поле или атрибуте система обращается к указанной в разделе SCOPE
таблице, чтобы убедиться в том, что в ней имеется строка, значение самоссылающегося столбца которой совпадает с сохраняемым ссылочным значением. Кроме того, если указывается REFERENCES ARE CHECKED
, то можно также указать ссылочное действие, которое должно выполняться при удалении строки, идентифицируемой ссылочным значением. Как обычно (см. лекцию 16), возможными ссылочными действиями являются RESTRICT
, CASCADE
, SET NULL
и NO ACTION
. Если ссылочное действие явно не указывается, по умолчанию принимается NO ACTION
. (Для поля строчного типа (ROW TYPE
) и атрибута структурного типа допускается только NO ACTION
.)
Заметим, что если раздел SCOPE
включается в определение атрибута структурного типа, то в конструкции column_options
столбца типизированной таблицы, соответствующего данному атрибуту, раздел SCOPE
присутствовать не может – это считается синтаксической ошибкой.
23.3.3. Выборка данных из типизированных таблиц
Приведем несколько примеров операций выборки данных из типизированных таблиц, а также кратко обсудим операции обновления таких таблиц. Для этого сначала определим структурные типы EMP_T
, PROGRAMMER_T
и DEPT_T
, а также соответствующие типизированные таблицы (упрощенный вариант).
CREATE TYPE EMP_T AS (
EMP_NAME VARCHAR(20),
EMP_BDATE DATE,
EMP_SAL SALARY,
DEPT REF (DEPT))
INSTANTIABLE
NOT FINAL
REF IS SYSTEM GENERATED
INSTANCE METHOD age ()
RETURNS DECIMAL (3,1);
CREATE TYPE PROGRAMMER_T UNDER EMP_T AS (
PROG_LANG VARCHAR (10))
INSTANTIABLE
NOT FINAL;
CREATE TYPE DEPT_T AS (
DEPT_NO INTEGER,
DEPT_NAME VARCHAR(200),
DEPT_MNG REF (EMP))
INSTANTIABLE
REF IS SYSTEM GENERATED
NOT FINAL;
CREATE TABLE EMP OF EMP_T
(REF IS DEPT_ID SYSTEM GENERATED,
DEPT WITH OPTIONS SCOPE DEPT);
CREATE TABLE PROGRAMMER OF PROGRAMMER_T UNDER EMP;
CREATE TABLE DEPT OF DEPT_T
(REF IS EMP_ID SYSTEM GENERATED,
DEPT_MNG WITH OPTIONS SCOPE EMP);
Следует отметить, что с типизированными таблицами можно работать, как с обычными таблицами203). Поэтому, в частности, возможен следующий запрос.
Пример 23.1. Найти имена всех служащих, размер заработной платы которых меньше 20000.00.
SELECT EMP_NAME
FROM EMP
WHERE EMP_SAL < 20000.00;
В соответствии с семантикой SQL:1999, при выполнении запроса из примера 23.1 сначала будет произведена выборка имен служащих, удовлетворяющих условию, из таблицы EMP
, затем – из таблицы PROGRAMMER
, и эти промежуточные результаты будут скомбинированы в окончательный результат путем применения операции объединения (UNION
). Но предположим, что нас интересуют только те служащие, получающие зарплату, не превышающую 20000 руб., которые не являются программистами (пример 23.2). Тогда можно применить формулировку запроса, в которой присутствует спецификация ONLY
:
Пример 23.2. Найти имена всех служащих, которые не являются программистами, размер заработной платы которых меньше 20000.00.
SELECT EMP_NAME
FROM ONLY (EMP)
WHERE EMP_SAL < 20000.00;
Естественно, в запросах к типизированным таблицам можно использовать ссылки.
Пример 23.3. Найти имена и названия отделов, где работают служащие, размер заработной платы которых меньше 20000.00.
SELECT EMP_NAME, DEPT -> DEPT_NAME
FROM EMP
WHERE EMP_SAL < 20000.00;
В SQL:1999 операция «->
» называется операцией разыменования (dereferencing), но в обиходе ее можно считать операцией перехода по ссылке (в нашем примере DEPT
ссылается на DEPT_NAME
). Можно неформально трактовать ссылочные значения как указатели на строки типизированных таблиц.
Может показаться неожиданным, что запрос из примера 23.3 выбирает значения из таблицы DEPT
, хотя в разделе FROM
этого запроса она даже не упоминается. Дело в том, что выполнение операции разыменования фактически приводит к выполнению соединения таблиц EMP
и DEPT
, делая в запросе столбец DEPT_NAME
«видимым».
Конечно, в запросе допускаются многократные переходы по ссылкам, так что можно сформулировать следующий запрос:
Пример 23.4. Найти имена служащих и имена руководителей их отделов для служащих, получающих зарплату, не превышающую 20000.00.
SELECT EMP_NAME, DEPT -> DEPT_MNG -> EMP_NAME
FROM EMP
WHERE EMP_SAL < 20000.00;
Как показывает следующий пример, в запросах можно использовать вызовы методов над строками, к которым производится переход по ссылке.
Пример 23.5. Найти имя и возраст руководителя отдела 605.
SELECT DEPT_MNG -> EMP_NAME, DEPT_MNG -> age ()
FROM DEPT
WHERE DEPT_NO = 605;
Наконец, имеется возможность полностью выбрать экземпляр структурного типа, идентифицируемый ссылочным значением (в SQL:1999 это называется разрешением ссылки – reference resolution).
Пример 23.6. Получить полные данные о руководителе отдела 605.
SELECT DEREF (DEPT_MNG)
FROM DEPT
WHERE DEPT_NO = 605;
В этом случае результатом запроса будет являться таблица, включающая один столбец структурного типа EMP_T
. Единственным значением этого столбца будет экземпляр (значение) этого структурного типа, соответствующий служащему-руководителю отдела 605.
Операции обновления типизированных таблиц выполняются очевидным образом. Операция INSERT
вставляет указанные строки в указанную таблицу. Операции DELETE
и UPDATE
удаляют или модифицируют строки в иерархии таблиц, корнем которой является указанная таблица, если в операции не содержится ONLY
. Если же специфицировано ONLY
, то удаляются или модифицируются только строки указанной таблицы.
202 Тип T
является непосредственным супертипом типа T'
в том и только том случае, когда T
является супертипом T'
, и не существует такого типа T''
, что T
является супертипом T''
, и T''
является супертипом T'
.
203 По крайней мере, в той же синтаксической форме.
Назад Содержание Вперёд