Хотя на вид (на примерах) выражения запросов 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.
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
3.3.3. Подзапросы
В стандарте SQL/92 специфицированы три вида подзапросов: скалярный, строчный и табличный. Скалярный подзапрос выдает одно значение некоторого типа; строчный подзапрос выдает одну строку; табличный подзапрос выдает таблицу. В основе каждого вида подзапроса лежит табличное выражение. Синтаксически соответствующие конструкции определяются следующими правилами:
<scalar subquery> ::= <subquery> <row subquery> ::= <subquery> <table subquery> ::= <subquery> <subquery> ::= <left paren> <query expression> <right paren>
Пояснения:
Теперь мы в состоянии привести синтаксические определения и соответствующие пояснения по поводу выражения запросов:
<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>
Пояснения:
(SELECTSLFROMTN1) OP (SELECTSLFROMTN2).
Внешне предикаты, которые можно использовать в условиях поиска 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>
Пояснения:
3.4.2. Предикат between
Как и в SQL/89, предикат позволяет специфицировать условие вхождения в диапазон значений, но в SQL/92 операндами являются строки:
<between predicate> ::=
<row value constructor> [ NOT ] BETWEEN
<row value constructor> AND <row value constructor>
Пояснения:
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> }...
Пояснения:
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 условие "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.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>
Пояснения:
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>
Пояснения:
(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>
Пояснения:
Таблица истинности для оператора 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 |
Назад | Содержание | Вперед