3.3. Выражения запросов
Хотя на вид (на примерах) выражения запросов SQL/92 очень напоминают соответствующие конструкции SQL/89, на самом деле они гораздо мощнее. Для того, чтобы можно было лучше понять существо выражений запросов SQL/92, мы начнем с рассмотрения вспомогательных конструкций. Заметим, что синтаксические определения часто носят рекурсивный характер, но это "хорошая" рекурсия, потому что в конечном счете любой запрос опирается на именованные базовые или представляемые таблицы.
Итак, сначала введем некоторые начальные понятия, связанные с запросами. Наверное, наиболее важным из таких понятий в SQL/92 является ссылка на таблицу (tablereference), которая может встречаться во всех конструкциях, адресуемых к таблицам. Ссылка на таблицу определяется следующими синтаксическими правилами:
<table reference> ::= <table name> [ [ AS ] <correlation name>
[ <left paren> <derived column list> <right paren> ] ]
|<derived table> [ AS ] <correlation name>
[ <left paren> <derived column list> <right paren> ]
|<joined table>
<derived table> ::= <table subquery>
<derived column list> ::= <column name list>
<column name list> ::=
<column name> [ { <comma> <column name> }... ]
Пояснения: Как видно, в отличие от SQL/89, где ссылка на таблицу всегда задается ее именем, в SQL/92 возможны еще два варианта: задать таблицу запросом в традиционной форме или выражением с использованием операторов соединения. Как выглядят эти два варианта, мы увидим в следующих подразделах.
Еще два понятия, более мелких, но необходимых, - конструктор значения-строки и конструктор значения-таблицы. Конструктор значения строки строит из скалярных значений упорядоченный набор, представляющий строку (возможно и использование подзапроса):
<row value constructor> ::=
<row value constructor element>
|<left paren> <row value constructor list> <right paren>
|<row subquery>
<row value constructor list> ::=
<row value constructor element>
[ { <comma> <row value constructor element> }... ]
<row value constructor element> ::=
<value expression>
|<null specification>
|<default specification>
<null specification> ::= NULL
<default specification> ::= DEFAULT
Заметим, что значение элемента по умолчанию можно использовать только в том случае, когда конструктор значения-строки используется в операторе INSERT (тогда этим значением будет значение по умолчанию соответствующего столбца).
Конструктор значения-таблицы производит таблицу на основе заданного набора конструкторов значений-строк:
<table value constructor> ::=
VALUES <table value constructor list>
<table value constructor list> ::=
<row value constructor>
[ { <comma> <row value constructor> }... ]
Пояснение: Конечно, для того, чтобы корректно построить таблицу, требуется, чтобы строки, производимые всеми конструкторами строк, были одной и той же степени и чтобы типы (или домены) соответствующих столбцов совпадали.
3.3.1. Табличные выражения
Как и в SQL/89, табличное выражение SQL/92 в качестве результата выдает обычную или сгруппированную таблицу:
<table expression> ::=
<from clause>
[ <where clause> ]
[ <group by clause> ]
[ <having clause> ]
Все отличия от SQL/89 сосредоточены в разделах табличного выражения.
3.3.1.1. Раздел FROM
Формально синтаксис остался таким же, как и в SQL/89:
<from clause> ::=
FROM <table reference>
[ { <comma> <table reference> }... ]
Но вспомним, что такое ссылка на таблицу в SQL/92 (см. выше). Реально можно весь запрос сосредоточить в разделе FROM.
3.3.1.2. Раздел WHERE
Снова синтаксис формально не изменился:
<where clause> ::= WHERE <search condition>
Но существенно расширен набор допустимых предикатов (см. следующий раздел).
Разделы GROUPBY и HAVING остались такими же, как в SQL/89, если не считать расширения набора предикатов, которые можно использовать в условии HAVING.
Минимальный осмысленный контекст использования табличных выражений составляет спецификация запроса - один из основных строительных блоков для построения выражения запросов. Синтаксис спецификации запросов следующий:
<query specification> ::=
SELECT [ <set quantifier> ] <select list> <table expression>
<select list> ::=
<asterisk>
|<select sublist> [ { <comma> <select sublist> }... ]
<select sublist> ::=
<derived column>
|<qualifier> <period> <asterisk>
<derived column> ::= <value expression> [ <as clause> ]
<as clause> ::= [ AS ] <column name>
Опять же на вид это очень похоже на соответствующую конструкцию SQL/89, но нужно иметь в виду, что, во-первых, в основе спецификации запроса SQL/92 лежит существенно расширенная конструкция табличного выражения, а во-вторых, в спецификации присутствует необязательный раздел AS, позволяющий присвоить имена таблице, которая генерируется при выполнении запроса. Эта возможность кажется на первый взгляд мелочью, но именно она позволяет использовать порождаемые таблицы в разделе FROM и отказаться от использования номеров столбцов порождаемой таблицы в разделе ORDERBY выражения запросов (см. ниже).
3.3.2. Соединенные таблицы
Конструкция соединенной таблицы - это альтернативный способ порождения новой таблицы на основе использования ранее определенных таблиц (базовых, представляемых или порожденных). Для этой конструкции аналоги в SQL/89 отсутствуют. Фактически соединенная таблица вносит алгебраический стиль в формулировки запросов на языке SQL. Формально соединенная таблица определяется следующими синтаксическими правилами:
<joined table> ::=
<cross join>
|<qualified join>
|<left paren> <joined table> <right paren>
<cross join> ::=
<table reference> CROSS JOIN <table reference>
<qualified join> ::=
<table reference> [ NATURAL ] [ <join type> ] JOIN
<table reference> [ <join specification> ]
<join specification> ::=
<join condition>
|<named columns join>
<join condition> ::= ON <search condition>
<named columns join> ::=
USING <left paren> <join column list> <right paren>
<join type> ::=
INNER
|<outer join type> [ OUTER ]
|UNION
<outer join type> ::=
LEFT
|RIGHT
|FULL
<join column list> ::= <column name list>
Поскольку раньше мы не встречались с подобными конструкциями, приведем сравнительно подробные объяснения. Предположим, что соединяются таблицы T1 и T2. Пусть CP обозначает их расширенное Декартово произведения: CP = SELECT * FROMT1, T2.
- Если специфицировано квалифицированное соединение (qualifiedjoin), то
(a) если указано NATURAL (естественное соединение), то спецификация соединения (joinspecification) должна отсутствовать;
(b) если указано UNION (объединение), то должны отсутствовать и спецификация соединения, и NATURAL;
(c) в противном случае спецификация соединения должна присутствовать.
- Если специфицировано квалифицированное соединение, и не указан тип соединения (jointype), то неявно предполагается внутреннее (INNER) соединение.
- Если специфицировано квалифицированное соединение с условием соединения (joincondition), то
(a) каждая ссылка на столбец, встречающаяся в условии поиска, должна однозначно указывать на столбец таблицы T1 или T2, либо быть внешней ссылкой (ссылкой на столбец запроса более высокого уровня);
(b) если выражение со значением, непосредственно содержащееся в условии поиска, является спецификацией агрегатной функции, то соединенная таблица должна содержаться в разделе HAVING или списке выборки, и спецификация агрегатной функции должна содержать ссылку на внешний столбец.
- Если не указано ни NATURAL, ни спецификация соединения, содержащая только имена столбцов соединения (namedcolumnsjoin), то описатели столбцов результата такие же, как описатели столбцов CP.
- Если указано NATURAL или если спецификация запроса содержит только имена столбцов соединения, то
(a) если указано NATURAL, то пусть именем общего столбца будет имя, являющееся именем столбца для в точности одного столбца T1 и именем столбца для в точности одного столбца T2. Столбцами соединения являются все столбцы T1 и T2 с общими именами;
(b) если указаны имена столбцов соединения, то каждое имя в этом списке имен должно быть именем столбца для в точности одного столбца T1 и именем столбца для в точности одного столбца T2. Пусть именем общего столбца является имя каждого такого столбца. Столбцами соединения являются столбцы T1 и T2, идентифицированные в списке столбцов соединения (joincolumnlist);
(c) пусть C1 и C2 пара соответствующих столбцов соединения из T1 и T2. Типы данных, на которых определены эти столбцы, должны быть совместимы;
(d) пусть SLCC - список выборки порожденных столбцов в форме COALESCE (TA.C, TB.C) ASC (см. п.3.2.4) для каждого столбца соединения в том порядке, в котором они появляются в T1;
(e) пусть SL1 - список выборки столбцов T1, не являющихся столбцами соединения, в том порядке, в котором они появляются в T1, а SL2 - аналогичный список для T2;
(f) описатели столбцов результата соединенной таблицы такие же, как описатели столбцов результата запроса SELECTSLCC, SLT1, SLT2 FROMTR1, TR2.
- Каждый столбец CR результата соединенной таблицы, который не является столбцом соединения и соответствует столбцу C1 таблицы T1, потенциально может содержать неопределенные значения, если выполняется любое из следующих условий:
(a) специфицировано RIGHT, FULL или UNION;
(b) специфицировано INNER, LEFT или CROSSJOIN, и столбец С1 потенциально может содержать неопределенные значения.
- Каждый столбец CR результата соединенной таблицы, который не является столбцом соединения и соответствует столбцу C2 таблицы T2, потенциально может содержать неопределенные значения, если выполняется любое из следующих условий:
(a) специфицировано LEFT, FULL или UNION;
(b) специфицировано INNER, RIGHT или CROSSJOIN, и столбец С2 потенциально может содержать неопределенные значения.
- Каждый столбец CR результата соединенной таблицы, который является столбцом соединения и соответствует столбцам C1 таблицы T1 и C2 таблицы T2, потенциально может содержать неопределенные значения, если выполняется любое из следующих условий:
(a) специфицировано RIGHT, FULL или UNION и столбец C1 потенциально может содержать неопределенные значения;
(b) специфицировано LEFT, FULL или CROSSJOIN, и столбец С2 потенциально может содержать неопределенные значения.
- Соединенная таблица является только читаемой.
- Определим T следующим образом:
(a) если тип соединения есть UNION, то пусть T будет пустым множеством;
(b) если специфицировано CROSSJOIN, то пусть T будет мультимножеством строк CP;
(c) если задано условие соединения, то пусть T будет мультимножеством строк CP, для которых заданное условие поиска вычисляется в true;
(d) если указаны NATURAL или имена столбцов соединения, то
(i) если имеются столбцы соединения, то пусть T будет мультимножеством строк CP, для которых соответствующие столбцы соединения имеют одинаковые значения;
(ii) в противном случае пусть T будет мультимножеством строк CP.
- Пусть P1 - мультимножество строк из T1, для которых в T существует некоторая строка, являющаяся конкатенацией некоторой строки R1 из P1 и некоторой строки R2 из T2. Пусть P2 - мультимножество строк из T2, для которых в T существует некоторая строка, являющаяся конкатенацией некоторой строки R1 из T1 и некоторой строки R2 из P2.
- Пусть мультимножество U1 составляют те строки из T1, которые не входят в P1, а U2 - строки, которые не входят в P2.
- Пусть D1 и D2 - степени T1 и T2 соответственно. Пусть X1 получается из U1 путем расширения вправо на D2 столбцов, содержащих неопределенные значения, а X2 - из U2 путем расширения влево на D1 столбцов, содержащих неопределенные значения.
- Результат соединенной таблицы S получается следующим образом:
(a) если задано INNER или CROSSJOIN, то S - мультимножество строк из T.
(b) если указано LEFT, то S - это мультимножество строк, вырабатываемое в результате следующего запроса:
SELECT * FROMT
UNIONALL
SELECT * FROMX1
(c) если указано RIGHT, то S - это мультимножество строк, вырабатываемое в результате следующего запроса:
SELECT * FROMT
UNIONALL
SELECT * FROMX2
(d) если указано FULL, то S - это мультимножество строк, вырабатываемое в результате следующего запроса:
SELECT * FROMT
UNIONALL
SELECT * FROMX1
UNIONALL
SELECT * FROMX2
(e) если указано UNION, то S - это мультимножество строк, вырабатываемое в результате следующего запроса:
SELECT * FROMX1
UNIONALL
SELECT * FROMX2
- Если указаны NATURAL или список имен столбцов соединения, то окончательный результат соединенной таблицы - это мультимножество строк из S, получаемое в результате выполнения следующего запроса: SELECTSLCC, SL1, SL2 FROMS. В противном случае окончательным результатом является S.
3.3.3. Подзапросы
В стандарте SQL/92 специфицированы три вида подзапросов: скалярный, строчный и табличный. Скалярный подзапрос выдает одно значение некоторого типа; строчный подзапрос выдает одну строку; табличный подзапрос выдает таблицу. В основе каждого вида подзапроса лежит табличное выражение. Синтаксически соответствующие конструкции определяются следующими правилами:
<scalar subquery> ::= <subquery>
<row subquery> ::= <subquery>
<table subquery> ::= <subquery>
<subquery> ::= <left paren> <query expression> <right paren>
Пояснения:
- Степень скалярного подзапроса должна быть равна 1.
- Степень строчного подзапроса должна быть больше 1.
- Тип данных скалярного подзапроса совпадает с типом данных соответствующего столбца выражения запросов.
- Типы данных столбцов строчного или табличного подзапроса совпадают с типами данных соответствующих столбцов выражения запросов.
- Если мощность скалярного или строчного подзапроса больше 1, то возбуждается исключительное условие.
Теперь мы в состоянии привести синтаксические определения и соответствующие пояснения по поводу выражения запросов:
<query expression> ::=
<non-join query expression>
|<joined table>
<non-join query expression> ::=
<non-join query term>
|<query expression> UNION [ ALL ]
[ <corresponding spec> ]
|<query term> <query expression> EXCEPT [ ALL ]
[ <corresponding spec> ] <query term>
<query term> ::=
<non-join query term>
|<joined table>
<non-join query term> ::=
<non-join query primary>
|<query term> INTERSECT [ ALL ]
[ <corresponding spec> ] <query primary>
<query primary> ::=
<non-join query primary>
|<joined table>
<non-join query primary> ::=
<simple table>
|<left paren> <non-join query expression> <right paren>
<simple table> ::=
<query specification>
|<table value constructor>
|<explicit table>
<explicit table> ::= TABLE <table name>
<corresponding spec> ::=
CORRESPONDING
[ BY <left paren> <corresponding column list> <right paren> ]
<corresponding column list> ::= <column name list>
Пояснения:
- Если в терме или выражении запросов без соединения присутствует теоретико-множественный оператор, то пусть T1, T2 и TR обозначают соответственно первый операнд, второй операнд и результат терма или выражения, а OP - используемую теоретико-множественную операцию.
- Если специфицировано CORRESPONDING, то
(a) одно имя столбца не должно быть специфицировано более одного раза для столбцов T1 и T2;
(b) по крайней мере один столбец T1 должен иметь имя, являющееся именем некоторого столбца T2;
(c) если список соответствия столбцов не задан, пусть SL обозначает список выборки с указанием имен столбцов, являющихся именами столбцов и в T1, и в T2, в том порядке, в котором эти имена фигурируют в T1;
(d) если список соответствия столбцов задан, то пусть SL обозначает список выборки с указанием тех имен столбцов, явно входящих в список соответствия, в том порядке, в котором эти имена фигурируют в списке соответствия; каждое имя столбца в списке соответствия должно быть именем столбца и T1, и T2;
(e) терм или выражение запросов без соединения эквивалентны следующему:
(SELECTSLFROMTN1) OP (SELECTSLFROMTN2).
- Если CORRESPONDING не указано, то T1 и T2 должны быть одинаковой степени.
- Если не задан теоретико-множественный оператор, то результатом вычисления выражения запросов является результат вычисления простой или соединенной таблицы.
- Если теоретико-множественный оператор задан, то результатом его применения является таблица, содержащая следующие строки:
(a) пусть R - строка, являющаяся дубликатом некоторой строки T1 или некоторой строки T2 или обоих; пусть m - число дубликатов R в T1, а n - число дубликатов R в T2;
(b) если специфицировано ALL, то
(i) если указана операция UNION, то число дубликатов R в T равно m + n;
(ii) если указана операция EXCEPT, то число дубликатов R в T равно max ((m-n),0);
(iii) если указана операция INTERSECT, то число дубликатов R в T равно min (m,n).
3.4. Допустимые предикаты и условия поиска
Внешне предикаты, которые можно использовать в условиях поиска SQL/92, очень похожи на предикаты SQL/89. Но, во-первых, ассортимент допустимых предикатов расширен, а во-вторых, возможности задания условий "старых" предикатов стали существенно шире. Поэтому мы перечислим все возможные предикаты с приведением их синтаксиса и кратких пояснений. В конце раздела будут приведены правила формулировки и семантика условий поиска.
Предикат позволяет специфицировать условие, результатом вычисления которого может быть true, false или unknown. В языке SQL/92 допустимы следующие предикаты:
<predicate> ::=
<comparison predicate>
|<between predicate>
|<in predicate>
|<like predicate>
|<null predicate>
|<quantified comparison predicate>
|<exists predicate>
|<unique predicate>
|<match predicate>
|<overlaps predicate>
3.4.1. Предикат сравнения
В SQL/92 этот предикат предназначен для спецификации сравнения двух строчных значений. Синтаксис предиката следующий:
<comparison predicate> ::=
<row value constructor> <comp op> <row value constructor>
<comp op> ::=
<equals operator>
|<not equals operator>
|<less than operator>
|<greater than operator>
|<less than or equals operator>
|<greater than or equals operator>
Пояснения:
- Строки-операнды должны быть одинаковой степени.
- Типы данных соответствующих значений строк-операндов должны быть совместимы.
- Пусть X и Y обозначают соответствующие элементы строк-операндов, а XV и YV - их значения
(a) если XV и/или YV являются неопределенными значениями, то значение условия "X <compop> Y" есть unknown;
(b) если XV и YV не являются неопределенными значениями, то значением условия "X <compop> Y" является true или false в соответствии с естественными правилами применения операции сравнения.
- Числа сравниваются в соответствии с алгебраическими значениями.
- Сравнение двух текстовых строк производится следующим образом:
(a) если длина в символах строки X не равна длине строки Y, то для выравнивания длин строк более короткая строка расширяется символом набивки (padsymbol); если не используется явно специфицируемый порядок сортировки для используемого набора символов, то в качестве символа набивки используется пробел;
(b) далее производится лексикографическое сравнение строк в соответствии с предопределенным или явно определенным порядком сортировки символов.
- Сравнение двух битовых строк X и Y основано на сравнении соответствующих бит. Если Xi и Yi - значения i-тых бит X и Y соответственно и если LX и LY обозначает длину в битах X и Y соответственно, то
(a) X равно Y тогда и только тогда, когда LX = LY и Xi = Yi для всех i;
(b) X меньше Y тогда и только тогда, когда
(i) LX < LY и Xi = Yi для всех i меньших или равных LX, или
(ii) Xi = Yi для всех i < n и Xn = 0, а Yn =1 для некоторого n меньшего или равного min (LX,LY).
- Сравнение двух значений типа дата-время производится в соответствии с видом интервала, получающегося при вычитании второго значения из первого. Пусть X и Y - сравниваемые значения, а H - наименее значимое поле даты-времени X и Y. Результат сравнения X <compop> Y определяется как (X - Y) H <compop> INTERVAL (0) H. (Два значения типа дата-время сравнимы только в том случае, если они содержат одинаковый набор полей даты-времени.)
- Пусть Rx и Ry обозначают строки-операнды, а RXi и RXi - i-тые элементы Rx и Ry соответственно. Результат сравнения "Rx <compop> Ry" определяется следующим образом:
(a) "Rx = Ry" есть true тогда и только тогда, когда RXi = RYi для всех i;
(b) "Rx <> Ry" есть true тогда и только тогда, когда RXi <> RYi для некоторого i;
(c) "Rx < Ry" есть true тогда и только тогда, когда RXi = RYi для всех i < n, и RXn < RYn для некоторого n;
(d) "Rx > Ry" есть true тогда и только тогда, когда RXi = RYi для всех i < n, и RXn > RYn для некоторого n;
(e) "Rx <= Ry" есть true тогда и только тогда, когда Rx = Ry или Rx < Ry;
(f) "Rx >= Ry" есть true тогда и только тогда, когда Rx = Ry или Rx > Ry;
(g) "Rx = Ry" есть false тогда и только тогда, когда "Rx <> Ry" есть true.
(h) "Rx <> Ry" есть false тогда и только тогда, когда "Rx = Ry" есть true.
(i) "Rx < Ry" есть false тогда и только тогда, когда "Rx >= Ry" есть true.
(j) "Rx > Ry" есть false тогда и только тогда, когда "Rx <= Ry" есть true.
(k) "Rx <= Ry" есть false тогда и только тогда, когда "Rx > Ry" есть true.
(l) "Rx >= Ry" есть false тогда и только тогда, когда "Rx < Ry" есть true.
(m) "Rx <compop> Ry" есть unknown тогда и только тогда, когда "Rx <compop> Ry" не есть true или false.
3.4.2. Предикат between
Как и в SQL/89, предикат позволяет специфицировать условие вхождения в диапазон значений, но в SQL/92 операндами являются строки:
<between predicate> ::=
<row value constructor> [ NOT ] BETWEEN
<row value constructor> AND <row value constructor>
Пояснения:
- Все три строки-операнды должны иметь одну и ту же степень.
- Типы данных соответствующих значений строк-операндов должны быть совместимыми.
- Пусть X, Y и Z обозначают первый, второй и третий операнды.
- "XNOTBETWEENYANDZ" эквивалентно "NOT (XBETWEENYANDZ)".
- "XBETWEENYANDZ" эквивалентно "X>=YANDX<=Z".
3.4.3. Предикат in
Предикат позволяет специфицировать условие вхождения строчного значения в указанное множество значений. Синтаксические правила следующие:
<in predicate> ::=
<row value constructor>
[ NOT ] IN <in predicate value>
<in predicate value> ::=
<table subquery>
|<left paren> <in value list> <right paren>
<in value list> ::=
<value expression> { <comma> <value expression> }...
Пояснения:
- Пусть IVL обозначает список включаемых значений (<invaluelist>). Тогда (IVL) эквивалентно конструктору табличного значения (VALUESIVL).
- Пусть RVC обозначает строку-первый операнд, а IPV - множество значений (<inpredicatevalue>.
- Выражение RVCNOTINIPV эквивалентно NOT (RVCINIPV).
- Выражение RVCINIPV эквивалентно RVC = ANYIPV.
3.4.4. Предикат like
Формально предикат определяется следующими синтаксическими правилами:
<like predicate> ::=
<match value> [ NOT ] LIKE <pattern>
[ ESCAPE <escape character> ]
<match value> ::= <character value expression>
<pattern> ::= <character value expression>
<escape character> ::= <character value expression>
Пояснения: Если не считать того, что в соответствующем условии можно использовать выражения, вырабатывающие значения типа символьных строк, и того, что для используемого набора символов может быть явно задан порядок сортировки, смысл предиката LIKE в SQL/92 не изменился по сравнению с SQL/89.
3.4.5. Предикат null
Как и в SQL/89, предикат null позволяет проверить, не является ли значение неопределенным, но теперь в нем можно использовать операнд-строку:
<null predicate> ::= <row value constructor> IS [ NOT ] NULL
Пояснения:
- Пусть R обозначает значение строки-операнда.
- Если все значения, входящие в R, являются неопределенными, значение условия "RISNULL" есть true; иначе - false.
- Если ни одно из значений R не является неопределенным, то значением условия "RISNOTNULL" является true; иначе - false.
Замечание: для всех R условие "RISNOTNULL" имеет то же значение, что условие "NOTRISNULL" в том и только в том случае, когда степень R равна 1. Полная семантика предиката null приведена в следующей таблице:
Условие | RISNULL | RISNOTNULL | NOTRISNULL | NOTRISNOTNULL |
Степень 1: null | true | false | false | true |
Степень 1: notnull | false | true | true | false |
Степень > 1: все null | true | false | false | true |
degree > 1: есть null | false | false | true | true |
degree > 1: нет null | false | true | true | false |
3.4.6. Предикат сравнения с квантором
Этот предикат позволяет специфицировать квантифицированное сравнение строчного значения и определяется следующими синтаксическими правилами:
<quantified comparison predicate> ::=
<row value constructor>
<comp op> <quantifier> <table subquery>
<quantifier> ::= <all> <some>
<all> ::= ALL
<some> ::= SOME ANY
Пояснения:
- Степень первого операнда должна быть такой же, как и степень табличного подзапроса.
- Типы данных значений строки-операнда должны быть совместимы с типами данных соответствующих столбцов табличного подзапроса.
- Сравнение строк производится по тем же правилам, что и для предиката сравнения (п. 3.4.1).
- В остальном вычисление условий с кванторами some и all производится так же, как для предиката с квантором в языке SQL/89.
3.4.7. Предикат exists
Этот предикат имеет тот же смысл, что и соответствующий предикат языка SQL/89, но теперь его операндом может быть табличный подзапрос:
<exists predicate> ::= EXISTS <table subquery>
Пояснение: Если мощность табличного подзапроса больше нуля, то значение соответствующего условия есть true; иначе - false.
3.4.8. Предикат unique
Этот предикат позволяет сформулировать условие отсутствия дубликатов в результате запроса:
<unique predicate> ::= UNIQUE <table subquery>
Пояснение: результат вычисления условия UNIQUE <tablesubquery> есть true, если в таблице-результате вычисления табличного подзапроса нет таких двух строк, что значение каждого столбца одной строки не является неопределенным и равным значению соответствующего столбца второй строки; в противном случае значение условия есть false.
3.4.9. Предикат match
Предикат позволяет сформулировать условие соответствия строчного значения результату табличного подзапроса. Синтаксис определяется следующим правилом:
<match predicate> ::=
<row value constructor>
MATCH [ UNIQUE ] [ PARTIAL FULL ] <table subquery>
Пояснения:
- Степень первого операнда должна совпадать со степенью табличного подзапроса.
- Типы данных первого операнда должны быть совместимы с типами соответствующих столбцов табличного подзапроса.
- Сравнение пар соответствующих значений производится аналогично тому, как это специфицировалось для предиката сравнения.
- Пусть R обозначает строку-первый операнд.
- Если не указано ни PARTIAL, ни FULL, то
(a) если некоторое значение в R является неопределенным, то значением условия является true;
(b) если в R нет неопределенных значений, то
(i) если не указано UNIQUE и существует (возможно, не уникальная) строка RTi в результате табличного подзапроса такая, что R = RTi, то значение условия есть true;
(ii) если указано UNIQUE и в результате табличного подзапроса существует уникальная строка RTi такая, что R = RTi, то значение условия есть true;
(iii) в противном случае значением условия является false.
- Если указано PARTIAL, то
(a) если все значения в R неопределенные, то значение условия есть true;
(b) иначе:
(i) если не указано UNIQUE и в результате табличного подзапроса существует (возможно, не уникальная) строка RTi такая, что каждое отличное от неопределенного значение R равно соответствующему значению RTi, то значение условия есть true;
(ii) если указано UNIQUE и в табличном подзапросе существует уникальная строка RTi такая, что каждое отличное от неопределенного значение R равно соответствующему значению RTi, то значение условия есть true;
(iii) в противном случае значение условия есть false.
- Если указано FULL, то
(a) если все значения в R неопределенные, то значение условия есть true.
(b) если в R нет неопределенных значений, то
(i) если не указано UNIQUE и в результате табличного подзапроса существует (возможно, не уникальная) строка RTi такая, что R = RTi, то значение условия есть true;
(ii) если указано UNIQUE и в результате табличного подзапроса существует уникальная строка RTi такая, что R = RTi, то значение условия есть true;
(iii) в противном случае значение условия есть false;
(c) в противном случае значение условия есть false.
3.4.10. Предикат overlaps
Этот предикат служит для проверки перекрытия во времени двух событий. Условие определяется следующим синтаксисом:
<overlaps predicate> ::=
<row value constructor 1> OVERLAPS
<row value constructor 2>
<row value constructor 1> ::= <row value constructor>
<row value constructor 2> ::= <row value constructor>
Пояснения:
- Степень каждой из строк-операндов должна быть равна 2.
- Тип данных первого столбца каждого из операндов должен быть типом даты-времени, и типы данных первых столбцов должны быть совместимы.
- Тип данных второго столбца каждого из операндов должен быть типом даты-времени или интервала.
(a) если это тип интервала, то точность типа должна быть такой, чтобы интервал можно было прибавить к значению типа дата-время первого столбца;
(b) если это тип дата-время, то он должен быть совместим с типом данных дата-время первого столбца.
- Пусть D1 и D2 обозначают значения первого столбца первого и второго операндов соответственно.
- Если второй столбец первого операнда имеет тип дата-время, то пусть E1 обозначает его значение.
- Если второй столбец первого операнда имеет тип INTERVAL, то пусть I1 обозначает его значение, а E1 = D1 + I1.
- Если D1 - неопределенное значение или если E1 < D1, то пусть S1 = E1 и T1 = D1. Иначе, пусть S1 = D1 и T1 = E1.
- Аналогично определяются S2 и T2 применительно ко второму операнду.
- Результат условия совпадает с результатом вычисления следующего выражения:
(S1 > S2 ANDNOT (S1 >= T2 ANDT1 >= T2))
OR
(S2 > S1 ANDNOT (S2 >= T1 ANDT2 >= T1))
OR
(S1 = S2 AND (T1 <> T2 ORT1 = T2))
3.4.11. Условие поиска
Условие поиска принимает значения true, false или unknown в зависимости от результата применения булевских операторов к составляющим его простым условиям. Синтаксис и семантика условия поиска в SQL/92 практически такие же, как в SQL/89, но в стандарте SQL/92 более четко специфицирована трехзначная логика, в которой происходит вычисление условия поиска. Синтаксис определяется следующими правилами:
<search condition> ::=
<boolean term>
|<search condition> OR <boolean term>
<boolean term> ::=
<boolean factor>
|<boolean term> AND <boolean factor>
<boolean factor> ::= [ NOT ] <boolean test>
<boolean test> ::=
<boolean primary> [ IS [ NOT ] <truth value> ]
<truth value> ::=
TRUE
|FALSE
|UNKNOWN
<boolean primary> ::=
<predicate>
| <left paren> <search condition> <right paren>
Пояснения:
- Если условие поиска не содержит булевских операторов, то результат его вычисления совпадает с результатом составляющего его простого условия, задаваемого одним из перечисленных выше предикатов.
- NOT(true) есть false, NOT(false) есть true и NOT(unknown) есть unknown. Правила применения других булевских операторов задаются следующими таблицами истинности:
Таблица истинности для оператора AND
| true | false | unknown |
true | true | false | unknown |
false | false | false | false |
unknown | unknown | false | unknown |
Таблица истинности для оператора OR
| true | false | unknown |
true | true | true | true |
false | true | false | unknown |
unknown | true | unknown | unknown |
Таблица истинности для оператора IS
| true | false | unknown |
true | true | true | false |
false | false | true | false |
unknown | false | false | unknown |
Назад |
Содержание |
Вперед