Spec-Zone.ru › SQLite

ВЫБОР

Содержание
1. Обзор
2. Простой выбор данных
2.1. Определение входных данных (обработка предложения FROM)
2.2. Специальная обработка CROSS JOIN.
2.3. Фильтрация в предложении WHERE.
2.4. Генерация набора строк результатов
2.5. Одиночные столбцы в агрегированном запросе
2.6. Удаление дублированных строк (обработка DISTINCT)
3. Сложные операторы SELECT
4. Предложение ORDER BY
5. Предложение LIMIT
6. Предложение VALUES
7. Предложение WITH
8. Функции, возвращающие таблицы, в предложении FROM
9. Отклонения от стандартного SQL
9.1. Странные имена соединений
9.2. Гибкий синтаксис соединения
9.3. Приоритет соединений с запятыми и CROSS JOIN

1. Обзор

select-stmt:

С РЕКУРСИВНАЯ общее_выражение_с_таблицей , ВЫБРАТЬ РАЗЛИЧНЫЕ столбец_результата , ВСЕ ИЗ таблица_или_подзапрос условие_соединения , ГДЕ выражение СГРУППИРОВАТЬ ПО выражение С_УСЛОВИЕМ выражение , ОКНО
window-name AS window-defn , значения ( выражение ) , , составной-оператор select-core СОРТИРОВАТЬ ПО ОГРАНИЧИТЬ выражение элемент-сортировки , смещение выражение , выражение

общие-табличные-выражения:

имя_таблицы ( имя_столбца ) AS НЕ МАТЕРИАЛИЗОВАНО ( запрос_выборки ) ,

сложный_оператор:

ОБЪЕДИНЕНИЕ ОБЪЕДИНЕНИЕ ПЕРЕСЕЧЕНИЕ ИСКЛЮЧЕНИЕ ВСЕ

выражение:

литеральное значение связываемый параметр имя схемы . имя таблицы . имя столбца унарный оператор выражение выражение бинарный оператор выражение имя функции ( аргументы функции ) фильтрующее условие over-условие ( выражение ) , CAST ( выражение AS имя типа
) expr COLLATE collation-name expr НЕ ПОДОБНО GLOB REGEXP MATCH expr expr ESCAPE expr expr ISNULL NOTNULL НЕ NULL expr ЯВЛЯЕТСЯ НЕ РАЗЛИЧНЫМ ИЗ expr
expr НЕ МЕЖДУ expr И expr expr НЕ В ( запрос-выбор ) expr , имя-схемы . функция-таблицы ( expr ) имя-таблицы , НЕ СУЩЕСТВУЕТ ( запрос-выбор )
CASE expr WHEN expr THEN expr ELSE expr END raise-function

filter-clause:

FILTER ( WHERE expr )

function-arguments:

DISTINCT expr , * ORDER BY ordering-term ,

literal-value:

CURRENT_TIMESTAMP числовое_литерал строковое_литерал двоичное_литерал NULL ИСТИНА ЛОЖЬ ТЕКУЩЕЕ_ВРЕМЯ ТЕКУЩАЯ_ДАТА

оператор_over:

СВЕРХУ имя-окна ( основное-имя-окна РАЗДЕЛЁННЫЙ ПО выражение , ПОРЯДОК ПО свойство-упорядочения , спецификация-кадра )

спецификация-кадра:

ГРУППЫ МЕЖДУ НЕОГРАНИЧЕННЫМИ ПРЕДШЕСТВУЮЩИМИ И НЕОГРАНИЧЕННЫМИ ПОСЛЕДУЮЩИМИ ДИАПАЗОН СТРОКИ НЕОГРАНИЧЕННЫМИ ПРЕДШЕСТВУЮЩИМИ expr ПРЕДШЕСТВУЮЩИМИ ТЕКУЩАЯ СТРОКА expr ПРЕДШЕСТВУЮЩИМИ ТЕКУЩАЯ СТРОКА expr ПОСЛЕДУЮЩИМИ expr ПРЕДШЕСТВУЮЩИМИ ТЕКУЩАЯ СТРОКА expr ПОСЛЕДУЮЩИМИ
ИСКЛЮЧИТЬ ТЕКУЩИЙ РЯД ИСКЛЮЧИТЬ ГРУППА ИСКЛЮЧИТЬ СВЯЗИ ИСКЛЮЧИТЬ НЕТ ДРУГИЕ

raise-function:

ПОДНЯТЬ ( ОТКАТ , сообщение_ошибки ) ИГНОРИРОВАТЬ ПРЕРВАТЬ НЕУДАЧА

имя_типа:

имя ( число со знаком , число со знаком ) ( число со знаком )

число со знаком:

+ числовое значение -

Запрос объединения:

table-or-subquery join-operator table-or-subquery join-constraint

join-constraint:

USING ( column-name ) , ON expr

join-operator:

NATURAL LEFT OUTER JOIN , RIGHT FULL INNER CROSS

ordering-term:

expr COLLATE имя_сортировки по убыванию по возрастанию NULL первым NULL последним

столбец_результата:

expr КАК псевдоним_столбца * имя_таблицы . *

таблица_или_подзапрос:

имя-схемы . имя-таблицы КАК алиас-таблицы ИНДЕКСИРОВАН ПО имя-индекса НЕ ИНДЕКСИРОВАН имя-функции-таблицы ( выражение ) , КАК алиас-таблицы ( выражение-выбора ) ( таблица-или-подзапрос ) ,
join-clause

window-defn:

( base-window-name PARTITION BY expr , ORDER BY ordering-term , frame-spec )

frame-spec:

ГРУППЫ МЕЖДУ НЕОГРАНИЧЕННАЯ ПРЕДШЕСТВУЮЩИХ И НЕОГРАНИЧЕННАЯ СЛЕДУЮЩИХ ДΙΑПАЗОН СТРОКИ НЕОГРАНИЧЕННАЯ ПРЕДШЕСТВУЮЩИХ expr ПРЕДШЕСТВУЮЩИХ ТЕКУЩИЙ СТРОКА expr ПРЕДШЕСТВУЮЩИХ ТЕКУЩИЙ СТРОКА expr СЛЕДУЮЩИХ expr ПРЕДШЕСТВУЮЩИХ ТЕКУЩИЙ СТРОКА expr СЛЕДУЮЩИХ
EXCLUDE CURRENT ROW EXCLUDE GROUP EXCLUDE TIES EXCLUDE NO OTHERS

Запрос SELECT используется для запроса базы данных. Результат SELECT — это ноль или более строк данных, где каждая строка имеет фиксированное количество столбцов. Запрос SELECT не вносит никаких изменений в базу данных.

Диаграмма синтаксиса "select-stmt" выше пытается показать как можно больше синтаксиса запроса SELECT в одной диаграмме, потому что некоторые читатели считают это полезным. Следующая диаграмма синтаксиса "factored-select-stmt" является альтернативным синтаксисом, который выражает тот же синтаксис, но пытается разбить синтаксис на более мелкие части.

factored-select-stmt:

С РЕКУРСИВНЫЙ общий-табличный-выражение , select-core СОРТИРОВКА ПО ОГРАНИЧЕНИЕ выражение сложный-оператор элемент-сортировки , СМЕЩЕНИЕ выражение , выражение

общий-табличный-выражение:

имя_таблицы ( имя_столбца ) КАК НЕ МАТЕРИАЛИЗОВАННЫЙ ( запрос_select ) ,

запрос_select:

С РЕКУРСИВНАЯ общее-выражение-с-подзапросом , ВЫБРАТЬ УНИКАЛЬНЫЕ столбец-результата , ВСЕ ИЗ таблица-или-подзапрос сложение-присоединения , ГДЕ выражение СГРУППИРОВАТЬ ПО выражение ПРИ выражение ,
ОКОННЫЙ имя-окна КАК определение-окна , ЗНАЧЕНИЯ ( выражение ) , , составной-оператор select-core СОРТИРОВКА ПО ОГРАНИЧЕНИЕ выражение элемент-сортировки , СМЕЩЕНИЕ выражение , выражение

оператор-соединения:

table-or-subquery join-operator table-or-subquery join-constraint

join-constraint:

USING ( column-name ) , ON expr

join-operator:

NATURAL LEFT OUTER JOIN , RIGHT FULL INNER CROSS

result-column:

expr AS имя_колонки * имя_таблицы . *

запрос_или_подзапрос_к_таблице:

schema-name . table-name AS table-alias INDEXED BY index-name NOT INDEXED table-function-name ( expr ) , AS table-alias ( select-stmt ) ( table-or-subquery ) ,
join-clause

window-defn:

( base-window-name PARTITION BY expr , ORDER BY ordering-term , frame-spec )

frame-spec:

ГРУППЫ МЕЖДУ НЕОГРАНИЧЕННЫЙ ПРЕДШЕСТВУЮЩИЙ И НЕОГРАНИЧЕННЫЙ СЛЕДУЮЩИЙ ДИАПАЗОН СТРОКИ НЕОГРАНИЧЕННЫЙ ПРЕДШЕСТВУЮЩИЙ выражение ПРЕДШЕСТВУЮЩИЙ ТЕКУЩИЙ СТРОКА выражение ПРЕДШЕСТВУЮЩИЙ ТЕКУЩИЙ СТРОКА выражение СЛЕДУЮЩИЙ выражение ПРЕДШЕСТВУЮЩИЙ ТЕКУЩИЙ СТРОКА выражение СЛЕДУЮЩИЙ
ИСКЛЮЧАТЬ ТЕКУЩИЙ СТРОКА ИСКЛЮЧАТЬ ГРУППА ИСКЛЮЧАТЬ СВЯЗИ ИСКЛЮЧАТЬ НЕТ ДРУГИЕ

сложный оператор:

ОБЪЕДИНЕНИЕ ОБЪЕДИНЕНИЕ ПЕРЕСЕЧЕНИЕ ИСКЛЮЧЕНИЕ ВСЕ

выражение:

литеральное значение связываемый параметр имя схемы . имя таблицы . имя столбца унарный оператор expr expr бинарный оператор expr имя функции ( аргументы функции ) filter-clause over-clause ( expr ) , CAST ( expr AS имя типа
) выражение COLLATE collation-name выражение НЕ LIKE GLOB REGEXP MATCH выражение выражение ESCAPE выражение выражение ISNULL NOTNULL НЕ NULL выражение IS НЕ DISTINCT FROM выражение
expr НЕ МЕЖДУ expr И expr expr НЕ В ( запрос-выражение ) expr , имя-схемы . функция-таблицы ( expr ) имя-таблицы , НЕ СУЩЕСТВУЕТ ( запрос-выражение )
CASE expr WHEN expr THEN expr ELSE expr END raise-function

filter-clause:

FILTER ( WHERE expr )

function-arguments:

DISTINCT expr , * ORDER BY ordering-term ,

literal-value:

CURRENT_TIMESTAMP numeric-literal string-literal blob-literal NULL TRUE FALSE CURRENT_TIME CURRENT_DATE

over-оператор:

ПЕРЕД имя-окна ( базовое-имя-окна РАЗДЕЛ ПО выражение , ПОРЯДОК ПО свойство-упорядочения , описание-фрейма )

описание-фрейма:

ГРУППЫ МЕЖДУ НЕОГРАНИЧЕННЫЕ ПРЕДШЕСТВУЮЩИЕ И НЕОГРАНИЧЕННЫЕ СЛЕДУЮЩИЕ ОБЛАСТЬ СТРОКИ НЕОГРАНИЧЕННЫЕ ПРЕДШЕСТВУЮЩИЕ выр ПРЕДШЕСТВУЮЩИЕ ТЕКУЩИЙ СТРОКА выр ПРЕДШЕСТВУЮЩИЕ ТЕКУЩИЙ СТРОКА выр СЛЕДУЮЩИЕ выр ПРЕДШЕСТВУЮЩИЕ ТЕКУЩИЙ СТРОКА выр СЛЕДУЮЩИЕ
Исключить Текущий Строка Исключить Группа Исключить Связи Исключить Нет Другие

raise-функция:

ВОЗВЫСИТЬ ( ОТКАТ , сообщение_об_ошибке ) ПРОИГНОРИРОВАТЬ ПРЕРВАТЬ НЕУДАЧА

заявление_SELECT:

С РЕКУРСИВНАЯ common-table-expression , ВЫБЕРИ УНИКАЛЬНЫЕ столбец-результата , ВСЕ ИЗ таблицы-или-подзапроса согласование , ГДЕ выражение ГРУППИРОВКА ПО выражение ПРИ выражение ,
ОКНО имя_окна КАК определение_окна , ЗНАЧЕНИЯ ( выражение ) , , бинарный_оператор select-core ПОРЯДОК ПО ОГРАНИЧЕНИЕ выражение элемент_упорядочивания , СМЕЩЕНИЕ выражение , выражение

оператор_соединения:

table-or-subquery join-operator table-or-subquery join-constraint

join-constraint:

USING ( column-name ) , ON expr

join-operator:

NATURAL LEFT OUTER JOIN , RIGHT FULL INNER CROSS

result-column:

expr AS имя_колонки * имя_таблицы . *

таблица или подзапрос:

schema-name . table-name AS table-alias INDEXED BY index-name NOT INDEXED table-function-name ( expr ) , AS table-alias ( select-stmt ) ( table-or-subquery ) ,
join-clause

window-defn:

( base-window-name PARTITION BY expr , ORDER BY ordering-term , frame-spec )

frame-spec:

ГРУППЫ МЕЖДУ НЕОГРАНИЧЕННЫМ ПРЕДШЕСТВУЮЩИМ И НЕОГРАНИЧЕННЫМ СЛЕДУЮЩИМ ДИАПАЗОН СТРОКИ НЕОГРАНИЧЕННЫМ ПРЕДШЕСТВУЮЩИМ expr ПРЕДШЕСТВУЮЩИМ ТЕКУЩАЯ СТРОКА expr ПРЕДШЕСТВУЮЩИМ ТЕКУЩАЯ СТРОКА expr СЛЕДУЮЩИМ expr ПРЕДШЕСТВУЮЩИМ ТЕКУЩАЯ СТРОКА expr СЛЕДУЮЩИМ
EXCLUDE CURRENT ROW EXCLUDE GROUP EXCLUDE TIES EXCLUDE NO OTHERS

type-name:

name ( signed-number , signed-number ) ( signed-number )

signed-number:

+ numeric-literal -

signed-number:

+ numeric-literal -

ordering-term:

expr COLLATE имя_сортировки ОБРАТНЫЙ ВОЗРАСТАНИЕ ПУСТО ПЕРВЫЙ ПУСТО ПОСЛЕДНИЙ

select-core:

ВЫБРАТЬ DISTINCT result-column , ВСЕ ИЗ table-or-subquery join-clause , ГДЕ expr ГРУППА ПО expr HAVING expr , ОКНО window-name КАК window-defn ,
ЗНАЧЕНИЯ ( expr ) , ,

оператор join:

table-or-subquery join-operator table-or-subquery join-constraint

join-constraint:

USING ( column-name ) , ON expr

join-operator:

NATURAL LEFT OUTER JOIN , RIGHT FULL INNER CROSS

result-column:

expr AS имя_колонки * имя_таблицы . *

таблица-или-подзапрос:

schema-name . table-name AS table-alias INDEXED BY index-name NOT INDEXED table-function-name ( expr ) , AS table-alias ( select-stmt ) ( table-or-subquery ) ,
состав-запроса

запрос:

С РЕКУРСИВНЫМ common-table-expression , ВЫБРАТЬ DISTINCT result-column , ВСЕ ИЗ table-or-subquery join-clause , ГДЕ expr ГРУППИРОВАТЬ ПО expr HAVING expr ,
ОКНО имя_окна КАК определение_окна , ЗНАЧЕНИЯ ( выражение ) , , оператор_соединения ядро_выбора ПОРЯДОК ПО ОГРАНИЧЕНИЕ выражение элемент_сортировки , СМЕЩЕНИЕ выражение , выражение

определение окна:

( имя-окна-базы РАЗДЕЛЁННЫЙ ПО выражение , ПОРЯДОК ПО термин-упорядочения , спецификация-рамки )

спецификация рамки:

ГРУППЫ МЕЖДУ НЕОГРАНИЧЕННЫЕ ПРЕДШЕСТВУЮЩИЕ И НЕОГРАНИЧЕННЫЕ СЛЕДУЮЩИЕ ДИАПАЗОН СТРОКИ НЕОГРАНИЧЕННЫЕ ПРЕДШЕСТВУЮЩИЕ expr ПРЕДШЕСТВУЮЩИЕ ТЕКУЩАЯ СТРОКА expr ПРЕДШЕСТВУЮЩИЕ ТЕКУЩАЯ СТРОКА expr СЛЕДУЮЩИЕ expr ПРЕДШЕСТВУЮЩИЕ ТЕКУЩАЯ СТРОКА expr СЛЕДУЮЩИЕ
EXCLUDE CURRENT ROW EXCLUDE GROUP EXCLUDE TIES EXCLUDE NO OTHERS

Обратите внимание, что есть пути по диаграммам синтаксиса, которые не допускаются на практике. Некоторые примеры:

  • Оператор VALUES может быть первым элементом в составном запросе SELECT, использующем оператор WITH, но простой запрос SELECT, состоящий только из оператора VALUES, не может предшествовать оператору WITH.
  • Оператор WITH должен находиться в первом запросе SELECT составного запроса SELECT. Он не может следовать за оператором соединения.

Эти и другие аналогичные ограничения синтаксиса описаны в тексте.

Оператор SELECT является наиболее сложной командой языка SQL. Чтобы описание было легче понять, некоторые разделы ниже описывают способ определения данных, возвращаемых оператором SELECT, как последовательность шагов. Важно помнить, что это чисто иллюстративно — на практике ни SQLite, ни другие SQL-движки не обязаны следовать этому или любому другому конкретному процессу.

2. Обработка простого запроса SELECT

Сердце оператора SELECT — это «простой запрос SELECT», показанный на диаграммах синтаксиса select-core и simple-select-stmt ниже. На практике большинство операторов SELECT являются простыми операторами SELECT.

simple-select-stmt:

END_OF_DOCUMENT_MARKER
С РЕКУРСИВНАЯ общий-табличный-выражение , select-core СОРТИРОВКА ПО ОГРАНИЧЕНИЕ выражение элемент-сортировки , СМЕЩЕНИЕ выражение , выражение

общее-табличное-выражение:

имя_таблицы ( имя_столбца ) КАК НЕ МАТЕРИАЛИЗОВАННЫЙ ( запрос_выбора ) ,

запрос_выбора:

WITH RECURSIVE common-table-expression , SELECT DISTINCT result-column , ALL FROM table-or-subquery join-clause , WHERE expr GROUP BY expr HAVING expr ,
ОКОШКО имя_окна КАК определение_окна , ЗНАЧЕНИЯ ( выражение ) , , сложный_оператор select-core СОРТИРОВКА ПО ОГРАНИЧЕНИЕ выражение элемент_сортировки , СМЕЩЕНИЕ выражение , выражение

сложный_оператор:

ОБЪЕДИНЕНИЕ ОБЪЕДИНЕНИЕ ПЕРЕСЕЧЕНИЕ ИСКЛЮЧЕНИЕ ВСЕ

оператор_соединения:

table-or-subquery join-operator table-or-subquery join-constraint

join-constraint:

USING ( column-name ) , ON expr

join-operator:

NATURAL LEFT OUTER JOIN , RIGHT FULL INNER CROSS

result-column:

expr AS имя_колонки * имя_таблицы . *

таблица или подзапрос:

имя-схемы . имя-таблицы КАК псевдоним-таблицы ИНДЕКСИРОВАН ПО имя-индекса НЕ ИНДЕКСИРОВАН имя-функции-таблицы ( выражение ) , КАК псевдоним-таблицы ( выражение-select ) ( таблица-или-подзапрос ) ,
join-clause

window-defn:

( base-window-name PARTITION BY expr , ORDER BY ordering-term , frame-spec )

frame-spec:

ГРУППЫ МЕЖДУ НЕОГРАНИЧЕННЫЕ ПРЕДШЕСТВУЮЩИЕ И НЕОГРАНИЧЕННЫЕ СЛЕДУЮЩИЕ ДΙΑПAЗОН СТРОКИ НЕОГРАНИЧЕННЫЕ ПРЕДШЕСТВУЮЩИЕ выражение ПРЕДШЕСТВУЮЩИЕ ТЕКУЩИЙ СТРОКА выражение ПРЕДШЕСТВУЮЩИЕ ТЕКУЩИЙ СТРОКА выражение СЛЕДУЮЩИЕ выражение ПРЕДШЕСТВУЮЩИЕ ТЕКУЩИЙ СТРОКА выражение СЛЕДУЮЩИЕ
EXCLUDE CURRENT ROW EXCLUDE GROUP EXCLUDE TIES EXCLUDE NO OTHERS

expr:

литеральное значение параметр привязки имя схемы . имя таблицы . имя столбца унарный оператор expr expr бинарный оператор expr имя функции ( аргументы функции ) фильтрующее условие over-clause ( expr ) , CAST ( expr AS имя типа
) expr COLLATE имя_сопоставления expr НЕ ПОДОБНО GLOB REGEXP MATCH expr expr ESCAPE expr expr ISNULL NOTNULL НЕ NULL expr ЯВЛЯЕТСЯ НЕ РАЗЛИЧНЫМ ИЗ expr
expr НЕ МЕЖДУ expr И expr expr НЕ В ( выражение-выборки ) expr , имя-схемы . функция-таблицы ( expr ) имя-таблицы , НЕ СУЩЕСТВУЕТ ( выражение-выборки )
СЛУЧАЙ expr КОГДА expr ТОГДА expr ИНАЧЕ expr КОНЕЦ функция-поднимания

оператор фильтрации:

ФИЛЬТР ( ГДЕ expr )

аргументы функции:

УНИКАЛЬНЫЕ expr , * ПОРЯДОК ПО условия-упорядочения ,

литеральное значение:

CURRENT_TIMESTAMP числовое_литерал строковое_литерал байтовый_литерал NULL ИСТИНА ЛОЖЬ ТЕКУЩЕЕ_ВРЕМЯ ТЕКУЩАЯ_ДАТА

оператор_over:

СВЕРХУ имя_окна ( базовое_имя_окна РАЗДЕЛ ПО выражение , ПОРЯДОК ПО термин_сортировки , спецификация_кадра )

спецификация_кадра:

ГРУППЫ МЕЖДУ НЕОГРАНИЧЕННЫЕ ПРЕДШЕСТВУЮЩИЕ И НЕОГРАНИЧЕННЫЕ СЛЕДУЮЩИЕ ДИАПАЗОН СТРОКИ НЕОГРАНИЧЕННЫЕ ПРЕДШЕСТВУЮЩИЕ выражение ПРЕДШЕСТВУЮЩИЕ ТЕКУЩАЯ СТРОКА выражение ПРЕДШЕСТВУЮЩИЕ ТЕКУЩАЯ СТРОКА выражение СЛЕДУЮЩИЕ выражение ПРЕДШЕСТВУЮЩИЕ ТЕКУЩАЯ СТРОКА выражение СЛЕДУЮЩИЕ
ИСКЛЮЧИТЬ ТЕКУЩИЙ РЯД ИСКЛЮЧИТЬ ГРУППА ИСКЛЮЧИТЬ СВЯЗИ ИСКЛЮЧИТЬ НЕТ ДРУГИЕ

raise-функция:

ВОЗВЫСИТЬ ( ОТКАТ ...

выражение_select:

С РЕКУРСИВНАЯ common-table-expression , ВЫБЕРИТЕ УНИКАЛЬНЫЕ столбец-результата , ВСЕ ИЗ таблицы-или-подзапроса сложения-таблиц , ГДЕ выражение СГРУППИРОВАТЬ ПО выражение ПРИ выражение ,
ОКОНО имя_окна КАК определение_окна , ЗНАЧЕНИЯ ( выражение ) , , оператор_сложного_выражения select-core ПОРЯДОК ПО ОГРАНИЧЕНИЕ выражение элемент_упорядочивания , СМЕЩЕНИЕ выражение , выражение

оператор_сложного_выражения:

ОБЪЕДИНЕНИЕ ОБЪЕДИНЕНИЕ ПЕРЕСЕЧЕНИЕ ИСКЛЮЧЕНИЕ ВСЕ

запрос JOIN:

table-or-subquery join-operator table-or-subquery join-constraint

join-constraint:

USING ( column-name ) , ON expr

join-operator:

NATURAL LEFT OUTER JOIN , RIGHT FULL INNER CROSS

result-column:

expr AS имя_колонки * имя_таблицы . *

таблица или подзапрос:

schema-name . table-name AS table-alias INDEXED BY index-name NOT INDEXED table-function-name ( expr ) , AS table-alias ( select-stmt ) ( table-or-subquery ) ,
join-clause

определение окна:

( имя_основного_окна РАЗДЕЛ ПО выражение , ПОРЯДОК ПО термин_упорядочения , спецификация_рамки )

спецификация_рамки:

ГРУППЫ МЕЖДУ НЕОГРАНИЧЕННЫЕ ПРЕДШЕСТВУЮЩИЕ И НЕОГРАНИЧЕННЫЕ СЛЕДУЮЩИЕ ДИАПАЗОН СТРОКИ НЕОГРАНИЧЕННЫЕ ПРЕДШЕСТВУЮЩИЕ expr ПРЕДШЕСТВУЮЩИЕ ТЕКУЩИЙ СТРОКА expr ПРЕДШЕСТВУЮЩИЕ ТЕКУЩИЙ СТРОКА expr СЛЕДУЮЩИЕ expr ПРЕДШЕСТВУЮЩИЕ ТЕКУЩИЙ СТРОКА expr СЛЕДУЮЩИЕ
Исключить Текущий Строка Исключить Группа Исключить Связи Исключить Нет Другие

имя типа:

имя ( число со знаком , число со знаком ) ( число со знаком )

число со знаком:

+ числовое значение -

порядок элемента:

expr COLLATE collation-name DESC ASC NULLS FIRST NULLS LAST

select-core:

ВЫБРАТЬ РАЗЛИЧНЫЕ столбец_результата , ВСЕ ИЗ таблица_или_подзапрос оператор_соединения , ГДЕ выражение ГРУППИРОВАТЬ ПО выражение ПРИ выражение , ОКОННАЯ имя_окна КАК определение_окна ,
ЗНАЧЕНИЯ ( expr ) , ,

оператор_соединения:

table-or-subquery join-operator table-or-subquery join-constraint

join-constraint:

USING ( column-name ) , ON expr

join-operator:

NATURAL LEFT OUTER JOIN , RIGHT FULL INNER CROSS

result-column:

expr AS имя_колонки * имя_таблицы . *

запрос_к_таблице_или_подзапрос:

имя-схемы . имя-таблицы КАК псевдоним-таблицы ИНДЕКСИРОВАН ПО имя-индекса НЕ ИНДЕКСИРОВАН имя-функции-таблицы ( выражение ) , КАК псевдоним-таблицы ( запрос-выбора ) ( таблица-или-подзапрос ) ,
join-clause

select-stmt:

С РЕКУРСИВНЫМ common-table-expression , ВЫБРАТЬ DISTINCT result-column , ВСЕ ИЗ table-or-subquery join-clause , ГДЕ expr ГРУППИРОВАТЬ ПО expr HAVING expr ,
WINDOW имя_окна КАК определение_окна , ЗНАЧЕНИЯ ( выражение ) , , бинарный_оператор ядро_выбора ПОРЯДОК ПО ОГРАНИЧЕНИЕ выражение элемент_упорядочения , СМЕЩЕНИЕ выражение , выражение

бинарный_оператор:

UNION UNION INTERSECT EXCEPT ALL

window-defn:

( base-window-name PARTITION BY expr , ORDER BY ordering-term , frame-spec )

frame-spec:

ГРУППЫ МЕЖДУ НЕОГРАНИЧЕННЫХ ПРЕДШЕСТВУЮЩИХ И НЕОГРАНИЧЕННЫХ СЛЕДУЮЩИХ ДИАПАЗОН СТРОКИ НЕОГРАНИЧЕННЫХ ПРЕДШЕСТВУЮЩИХ выражение ПРЕДШЕСТВУЮЩИХ ТЕКУЩЕЙ СТРОКИ выражение ПРЕДШЕСТВУЮЩИХ ТЕКУЩЕЙ СТРОКИ выражение СЛЕДУЮЩИХ выражение ПРЕДШЕСТВУЮЩИХ ТЕКУЩЕЙ СТРОКИ выражение СЛЕДУЮЩИХ
ИСКЛЮЧИТЬ ТЕКУЩИЙ РЯД ИСКЛЮЧИТЬ ГРУППА ИСКЛЮЧИТЬ СВЯЗИ ИСКЛЮЧИТЬ НЕТ ДРУГИЕ

Процесс генерации результатов простого оператора SELECT представлен в описании ниже в четырёх шагах:

  1. Обработка предложения FROM: Определяются входные данные для простого оператора SELECT. Входные данные — либо неявный единственный ряд с 0 столбцами (если предложение FROM отсутствует), либо определяемые предложением FROM.

  2. Обработка предложения WHERE: Входные данные фильтруются с помощью выражения предложения WHERE.

  3. Обработка GROUP BY, HAVING и выражений столбцов результата: Множество строк результата вычисляется путём агрегирования данных в соответствии с любым предложением GROUP BY и вычисления выражений результата для строк отфильтрованных входных данных.

  4. Обработка ключевых слов DISTINCT/ALL: Если запрос — «SELECT DISTINCT», из множества строк результата удаляются дублирующие строки.

Существует два типа простых операторов SELECT — агрегатные и неагрегатные запросы. Простой оператор SELECT — агрегатный, если он содержит предложение GROUP BY или один или несколько агрегатных функций в выражении результата. В противном случае, если простой оператор SELECT не содержит агрегатных функций или предложения GROUP BY, он является неагрегатным запросом.

2.1. Определение входных данных (обработка предложения FROM)

Входные данные, используемые простым оператором SELECT, представляют собой набор из N строк, каждая шириной M столбцов.

Если предложение FROM опущено из простого оператора SELECT, то входные данные неявно представляют собой одну строку нулевой ширины (т.е. N=1 и M=0).

Если предложение FROM указано, данные, на которых работает простой оператор SELECT, берутся из одной или нескольких таблиц или подзапросов (операторов SELECT в скобках), указанных после ключевого слова FROM. Подзапрос, указанный в table-or-subquery после предложения FROM в простом операторе SELECT, обрабатывается так, как будто это таблица, содержащая данные, полученные в результате выполнения оператора подзапроса. Каждый столбец подзапроса имеет порядок сортировки и аффинити соответствующего выражения в операторе подзапроса.

Если в предложении FROM указана только одна таблица или подзапрос, то входные данные, используемые оператором SELECT, — это содержимое указанной таблицы. Если в предложении FROM указано более одной таблицы или подзапроса, то содержимое всех таблиц и/или подзапросов объединяется в один набор данных для обработки простым оператором SELECT. Способ объединения данных зависит от конкретного оператора объединения и условия объединения, используемых для соединения таблиц или подзапросов.

Все объединения в SQLite основаны на декартовом произведении наборов данных слева и справа. Столбцы набора данных декартова произведения — это в порядке следования все столбцы набора данных слева, за которыми следуют все столбцы набора данных справа. В наборе данных декартова произведения есть строка, образованная путём объединения каждого уникального сочетания строки из левого и правого наборов данных. Другими словами, если левый набор данных состоит из Nleft строк по Mleft столбцов, а правый набор данных из Nright строк по Mright столбцов, то декартово произведение — это набор данных из Nleft×Nright строк, каждая из которых содержит Mleft+Mright столбцов.

Если оператор объединения — «CROSS JOIN», «INNER JOIN», «JOIN» или запятая (",") и нет предложения ON или USING, то результат объединения — просто декартово произведение левого и правого наборов данных. Если оператор объединения имеет предложения ON или USING, то они обрабатываются согласно следующим пунктам:

  • Если есть условие ON, то выражение ON вычисляется для каждой строки декартового произведения в качестве булевого выражения. В набор данных включаются только строки, для которых выражение вычисляется как true.

  • Если указан оператор USING, то каждое из указанных имён столбцов должно присутствовать в наборах данных слева и справа от оператора объединения. Для каждой пары именованных столбцов выражение "lhs.X = rhs.X" вычисляется для каждой строки декартового произведения в качестве булевого выражения. В набор результатов включаются только строки, для которых все такие выражения вычисляются как true. При сравнении значений в результате условия USING применяются обычные правила для обработки родственных типов, последовательностей сортировки и значений NULL при сравнениях. Столбец из набора данных слева от оператора объединения считается расположенным слева от оператора сравнения (=) для целей последовательности сортировки и приоритета родственных типов.

    Для каждой пары столбцов, определённых условием USING, столбец из правого набора данных исключается из объединённого набора данных. Это единственное различие между условием USING и эквивалентным условием ON.

  • Если в операторе объединения присутствует ключевое слово NATURAL, то к условиям объединения добавляется неявное условие USING. Неявное условие USING содержит все имена столбцов, которые появляются как в левом, так и в правом наборах входных данных. Если левые и правые наборы входных данных не имеют общих имён столбцов, то ключевое слово NATURAL не оказывает влияния на результаты объединения. К объединению, в котором указано ключевое слово NATURAL, нельзя добавить условие USING или ON.

  • Если оператор объединения — это «LEFT JOIN» или «LEFT OUTER JOIN», то после применения фильтрующих условий ON или USING к выходным данным добавляется дополнительная строка для каждой строки исходного левого набора входных данных, которая не совпадает ни с одной строкой правого набора данных. Добавляемые строки содержат значения NULL в столбцах, которые обычно содержат значения, скопированные из правого набора входных данных.

  • Если оператор объединения — это «RIGHT JOIN» или «RIGHT OUTER JOIN», то после применения фильтрующих условий ON или USING к выходным данным добавляется дополнительная строка для каждой строки исходного правого набора входных данных, которая не совпадает ни с одной строкой левого набора данных. Добавляемые строки содержат значения NULL в столбцах, которые обычно содержат значения, скопированные из левого набора входных данных.

  • «FULL JOIN» или «FULL OUTER JOIN» — это комбинация «LEFT JOIN» и «RIGHT JOIN». К выходным данным добавляются дополнительные строки для каждой строки левого набора данных, которая не совпадает ни с одной строкой правого, и для каждой строки правого набора данных, которая не совпадает ни с одной строкой левого. Несовпадающие столбцы заполняются NULL.

При объединении более двух таблиц в рамках предложения FROM операции объединения обрабатываются в порядке слева направо. Другими словами, предложение FROM (A join-op-1 B join-op-2 C) вычисляется как ((A join-op-1 B) join-op-2 C).

2.2. Особая обработка CROSS JOIN.

Нет разницы между операторами объединения «INNER JOIN», «JOIN» и «,». Они полностью взаимозаменяемы в SQLite. Оператор объединения «CROSS JOIN» производит тот же результат, что и операторы «INNER JOIN», «JOIN» и «,», но при этом обрабатывается оптимизатором запросов по-другому, предотвращая переупорядочение таблиц в объединении. Разработчик приложения может использовать оператор CROSS JOIN, чтобы напрямую повлиять на алгоритм, выбранный для реализации оператора SELECT. Избегайте использования CROSS JOIN, за исключением конкретных ситуаций, когда требуется ручное управление оптимизатором запросов. Избегайте использования CROSS JOIN на ранних этапах разработки приложения, так как это недопустимое оптимизирование. Специальная обработка CROSS JOIN — это функция, специфичная для SQLite, и она не входит в стандарт SQL.

2.3. Фильтрация с помощью предложения WHERE.

Если указано предложение WHERE, выражение WHERE вычисляется для каждой строки входных данных в качестве булевого выражения. В набор данных включаются только строки, для которых выражение предложения WHERE вычисляется как true, прежде чем продолжить обработку. Строки исключаются из результата, если выражение предложения WHERE вычисляется как false или NULL.

Для JOIN или INNER JOIN или CROSS JOIN нет разницы между выражением ограничения в предложении WHERE и в предложении ON. Однако для LEFT или RIGHT или FULL OUTER JOIN это различие очень важно. При внешнем объединении дополнительные строки NULL для несовпадающих строк на другом операнде добавляются после обработки предложения ON, но до обработки предложения WHERE. Ограничение вида "left.x=right.y" в предложении ON, следовательно, позволит пропустить все строки со значениями NULL. Но если это же ограничение находится в предложении WHERE, то значение NULL в одном из "right.y" или "left.x" предотвратит вычисление выражения "left.x=right.y" как true, и, таким образом, исключит эту строку из вывода.

2.4. Генерация набора строк результата

После фильтрации входных данных из предложения FROM с помощью выражения предложения WHERE (если оно указано), вычисляется набор строк результата для простого оператора SELECT. То, как это делается, зависит от того, является ли простой оператор SELECT агрегатным или нет, и было ли указано предложение GROUP BY.

Список выражений между словами SELECT и FROM называется списком выражений результата. Если выражение — это специальное выражение "*", то все столбцы входных данных подставляются вместо этого выражения. Если выражение — это псевдоним таблицы или подзапроса в предложении FROM, за которым следует ".*", то все столбцы из указанной таблицы или подзапроса подставляются вместо единственного выражения. Ошибка — использование выражения "*" или "alias.*" в любом контексте, кроме списка выражений результата. Также ошибка — использование выражения "*" или "alias.*" в простом операторе SELECT, у которого нет предложения FROM.

Количество столбцов в строках, возвращаемых простым оператором SELECT, равно количеству выражений в списке выражений результата после подстановки выражений * и alias.*. Каждая строка результата вычисляется путём вычисления выражений в списке выражений результата относительно одной строки входных данных или, для агрегатных запросов, относительно группы строк.

  • Если оператор SELECT является неагрегатным запросом, то каждое выражение в списке выражений результата вычисляется для каждой строки в наборе данных, отфильтрованных с помощью предложения WHERE.

  • Если оператор SELECT является агрегатным запросом без предложения GROUP BY, то каждое агрегатное выражение в наборе результатов вычисляется один раз для всего набора данных. Каждое неагрегатное выражение в наборе результатов вычисляется один раз для произвольно выбранной строки набора данных. Для каждого неагрегатного выражения используется одна и та же произвольно выбранная строка. Или, если набор данных содержит ноль строк, то каждое неагрегатное выражение вычисляется для строки, состоящей полностью из значений NULL.

    Единственная строка данных набора результатов, созданная путём вычисления агрегатных и неагрегатных выражений в наборе результатов, образует результат агрегатного запроса без предложения GROUP BY. Агрегатный запрос без предложения GROUP BY всегда возвращает ровно одну строку данных, даже если в наборе данных нет строк.

  • Если оператор SELECT является агрегатным запросом с предложением GROUP BY, то каждое из выражений, указанных в предложении GROUP BY, вычисляется для каждой строки набора данных в соответствии с правилами обработки, описанными ниже для выражений ORDER BY. Затем каждая строка присваивается к «группе» на основе результатов; строки, для которых результаты вычисления выражений GROUP BY одинаковы, присваиваются к одной и той же группе. Для целей группировки строк значения NULL считаются равными. Обычные правила для выбора последовательности сортировки для сравнения текстовых значений применяются при вычислении выражений в предложении GROUP BY. Выражения в предложении GROUP BY не должны быть выражениями, которые появляются в результате. Выражения в предложении GROUP BY не могут быть агрегатными выражениями.

    Если указано предложение HAVING, оно вычисляется один раз для каждой группы строк в качестве булевого выражения. Если результат вычисления предложения HAVING — false, группа отбрасывается. Если предложение HAVING — агрегатное выражение, оно вычисляется для всех строк в группе. Если предложение HAVING — неагрегатное выражение, оно вычисляется относительно произвольно выбранной строки из группы. Выражение HAVING может ссылаться на значения, даже агрегатные функции, которые не находятся в результате.

    Затем каждое выражение в наборе результатов вычисляется один раз для каждой группы строк. Если выражение — агрегатное выражение, оно вычисляется для всех строк в группе. В противном случае оно вычисляется для одной произвольно выбранной строки из группы. Если в наборе результатов более одного неагрегатного выражения, то все такие выражения вычисляются для одной и той же строки.

    Каждая группа строк входного набора данных вносит одну строку в набор строк результата. С учётом фильтрации, связанной с ключевым словом DISTINCT, количество строк, возвращаемых агрегатным запросом с предложением GROUP BY, совпадает с количеством групп строк, полученных путём применения предложений GROUP BY и HAVING к отфильтрованному набору входных данных.

2.5. Голые столбцы в агрегатном запросе

В обычном случае все имена столбцов в агрегатном запросе являются либо аргументами агрегатных функций, либо появляются в предложении GROUP BY. Столбец результата, который содержит имя столбца, не являющееся аргументом агрегатной функции и не появляющееся в предложении GROUP BY (если оно существует), называется «голым» столбцом. Пример:

SELECT a, b, sum(c) FROM tab1 GROUP BY a;

В запросе выше столбец «a» является частью предложения GROUP BY, и поэтому каждая строка вывода содержит одно из различных значений для «a». Столбец «c» содержится в агрегатной функции sum(), и поэтому столбец вывода представляет собой сумму всех значений «c» в строках, которые имеют одинаковое значение для «a». Но каков результат голого столбца «b»? Ответ заключается в том, что результат «b» будет значением «b» в одной из входных строк, которые формируют агрегат. Проблема в том, что вы обычно не знаете, какая входная строка используется для вычисления «b», и поэтому во многих случаях значение «b» не определено.

Специальная обработка происходит, когда агрегатная функция — это либо min(), либо max(). Пример:

SELECT a, b, max(c) FROM tab1 GROUP BY a;

Если в запросе присутствует ровно один агрегат min() или max(), то все базовые столбцы в наборе результатов принимают значения из входной строки, которая также содержит минимальное или максимальное значение. Таким образом, в запросе выше значение столбца "b" в выводе будет значением столбца "b" в входной строке, имеющей наибольшее значение столбца "c". Существуют ограничения на это специальное поведение агрегатов min() и max():

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

  2. Если в запросе присутствует два или более агрегата min() или max(), то значения базовых столбцов будут взяты из одной из строк, в которой один из агрегатов имеет минимальное или максимальное значение. Выбор того, какой агрегат min() или max() определяет выбор значений базовых столбцов, произвольный. Выбор может отличаться для разных базовых столбцов в одном и том же запросе.

  3. Это специальная обработка для агрегатов min() или max() работает только для встроенной реализации этих агрегатов. Если приложение переопределяет встроенные агрегаты min() или max() своими вариантами, то значения, выбранные для базовых столбцов, будут взяты из произвольной строки.

Большинство других СУБД SQL не позволяют использовать базовые столбцы. Если вы включаете базовый столбец в запрос, другие СУБД, как правило, генерируют ошибку. Возможность включать базовые столбцы в запрос является расширением, специфичным для SQLite. Это считается функцией, а не ошибкой. Дополнительную информацию см. в обсуждении на форуме SQLite 7481d2a6df8980ff.

2.6. Удаление дублирующих строк (обработка DISTINCT)

После ключевого слова SELECT в простом операторе SELECT может следовать ключевое слово ALL или DISTINCT. Если используется SELECT ALL, то возвращается весь набор строк результатов. Если ни ALL, ни DISTINCT не указаны, то поведение такое же, как если бы было указано ALL. Если используется SELECT DISTINCT, то дублирующие строки удаляются из набора строк результатов перед возвратом. Для определения дублирующих строк два значения NULL считаются равными. Применяются обычные правила для выбора порядка сортировки при сравнении текстовых значений.

3. Составные операторы SELECT

Два или более простых операторов SELECT можно объединить в составной оператор SELECT с помощью операторов UNION, UNION ALL, INTERSECT или EXCEPT, как показано на следующей диаграмме:

compound-select-stmt:

С РЕКУРСИВНЫЙ выражение_общего_табличного_выражения , select-core ПОРЯДОК ПО ОГРАНИЧЕНИЕ выражение ОБЪЕДИНЕНИЕ ОБЪЕДИНЕНИЕ ВСЕ select-core ПЕРЕСЕЧЕНИЕ ИСКЛЮЧЕНИЕ порядок_термин , СМЕЩЕНИЕ выражение , выражение

выражение_общего_табличного_выражения:

имя_таблицы ( имя_столбца ) КАК НЕ МАТЕРИАЛИЗОВАННОЕ ( выражение_select ) ,

выражение_select:

С РЕКУРСИВНАЯ выражение-с-общим-табличным-выражением , ВЫБРАТЬ УНИКАЛЬНЫЕ столбец-результата , ВСЕ ИЗ таблица-или-подзапрос условие-соединения , ГДЕ выражение ГРУППИРОВАТЬ ПО выражение С выражение ,
WINDOW window-name AS window-defn , ЗНАЧЕНИЯ ( expr ) , , сложный-оператор select-core ПОРЯДОК ПО ОГРАНИЧЕНИЕ expr элемент-упорядочения , СМЕЩЕНИЕ expr , expr

сложный-оператор:

ОБЪЕДИНЕНИЕ ОБЪЕДИНЕНИЕ ПЕРЕСЕЧЕНИЕ ИСКЛЮЧЕНИЕ ВСЕ

оператор_соединения:

table-or-subquery join-operator table-or-subquery join-constraint

join-constraint:

USING ( column-name ) , ON expr

join-operator:

NATURAL LEFT OUTER JOIN , RIGHT FULL INNER CROSS

result-column:

expr AS имя_колонки * название_таблицы . *

запрос_к_таблице_или_подзапрос:

schema-name . table-name AS table-alias INDEXED BY index-name НЕ INDEXED table-function-name ( expr ) , AS table-alias ( select-stmt ) ( table-or-subquery ) ,
join-clause

window-defn:

( base-window-name PARTITION BY expr , ORDER BY ordering-term , frame-spec )

frame-spec:

ГРУППЫ МЕЖДУ НЕОГРАНИЧЕННЫЕ ПРЕДШЕСТВУЮЩИЕ И НЕОГРАНИЧЕННЫЕ СЛЕДУЮЩИЕ ДИАПАЗОН СТРОКИ НЕОГРАНИЧЕННЫЕ ПРЕДШЕСТВУЮЩИЕ выражение ПРЕДШЕСТВУЮЩИЕ ТЕКУЩИЙ СТРОКА выражение ПРЕДШЕСТВУЮЩИЕ ТЕКУЩИЙ СТРОКА выражение СЛЕДУЮЩИЕ выражение ПРЕДШЕСТВУЮЩИЕ ТЕКУЩИЙ СТРОКА выражение СЛЕДУЮЩИЕ
ИСКЛЮЧИТЬ ТЕКУЩИЙ СТРОКА ИСКЛЮЧИТЬ ГРУППА ИСКЛЮЧИТЬ СВЯЗИ ИСКЛЮЧИТЬ НЕТ ДРУГИЕ

expr:

литеральное значение связываемый параметр имя схемы . имя таблицы . имя столбца унарный оператор expr expr бинарный оператор expr имя функции ( аргументы функции ) фильтрующее предложение над предложением ( expr ) , CAST ( expr AS имя типа
) expr COLLATE имя_сортировки expr НЕ СХОДСТВО GLOB REGEXP СОПОСТАВЛЕНИЕ expr expr ESCAPE expr expr ISNULL NOTNULL НЕ NULL expr ЯВЛЯЕТСЯ НЕ УНИКАЛЬНЫМ ИЗ expr
expr НЕ МЕЖДУ expr И expr expr НЕ В ( запрос-выбор ) expr , имя_схемы . функция_таблицы ( expr ) имя_таблицы , НЕ СУЩЕСТВУЕТ ( запрос-выбор )
CASE expr WHEN expr THEN expr ELSE expr END raise-function

filter-clause:

FILTER ( WHERE expr )

function-arguments:

DISTINCT expr , * ORDER BY ordering-term ,

literal-value:

CURRENT_TIMESTAMP numeric-literal string-literal blob-literal NULL ИСТИНА ЛОЖЬ CURRENT_TIME CURRENT_DATE

over-clause:

ПЕРЕД имя-окна ( основное-имя-окна РАЗДЕЛ ПО выражение , ПОРЯДОК ПО условие-упорядочения , описание-кадра )

описание-кадра:

ГРУППЫ МЕЖДУ НЕОГРАНИЧЕННЫМ ПРЕДШЕСТВУЮЩИМ И НЕОГРАНИЧЕННЫМ ПОСЛЕДУЮЩИМ ДИАПАЗОН СТРОКИ НЕОГРАНИЧЕННЫМ ПРЕДШЕСТВУЮЩИМ expr ПРЕДШЕСТВУЮЩИМ ТЕКУЩАЯ СТРОКА expr ПРЕДШЕСТВУЮЩИМ ТЕКУЩАЯ СТРОКА expr ПОСЛЕДУЮЩИМ expr ПРЕДШЕСТВУЮЩИМ ТЕКУЩАЯ СТРОКА expr ПОСЛЕДУЮЩИМ
ИСКЛЮЧИТЬ ТЕКУЩИЙ РЯД ИСКЛЮЧИТЬ ГРУППА ИСКЛЮЧИТЬ СВЯЗИ ИСКЛЮЧИТЬ НЕТ ДРУГИЕ

функция raise:

ВОЗБУДИТЬ ( ВОССТАНОВЛЕНИЕ , сообщение_об_ошибке ) ПРОИГНОРИРОВАТЬ ПРЕКРАТИТЬ ПРОВАЛ

выражение_select:

С РЕКУРСИВНАЯ общие-выражения-с-подзапросами , ВЫБРАТЬ РАЗЛИЧНЫЕ столбец-результата , ВСЕ ИЗ таблица-или-подзапрос присоединение , ГДЕ выражение СГРУППИРОВАТЬ ПО выражение ПРИ выражение , С
WINDOW window-name AS window-defn , ЗНАЧЕНИЯ ( expr ) , , сложный-оператор select-core СОРТИРОВКА ПО ОГРАНИЧЕНИЕ expr элемент-сортировки , СМЕЩЕНИЕ expr , expr

сложный-оператор:

ОБЪЕДИНЕНИЕ ОБЪЕДИНЕНИЕ ПЕРЕСЕЧЕНИЕ ИСКЛЮЧЕНИЕ ВСЕ

оператор объединения:

table-or-subquery join-operator table-or-subquery join-constraint

join-constraint:

USING ( column-name ) , ON expr

join-operator:

NATURAL LEFT OUTER JOIN , RIGHT FULL INNER CROSS

result-column:

expr AS имя_столбца * имя_таблицы . *

таблица или подзапрос:

schema-name . table-name AS table-alias INDEXED BY index-name NOT INDEXED table-function-name ( expr ) , AS table-alias ( select-stmt ) ( table-or-subquery ) ,
join-clause

window-defn:

( base-window-name PARTITION BY expr , ORDER BY ordering-term , frame-spec )

frame-spec:

ГРУППЫ МЕЖДУ НЕОГРАНИЧЕННЫМ ПРЕДШЕСТВУЮЩИМ И НЕОГРАНИЧЕННЫМ СЛЕДУЮЩИМ ДИАПАЗОН СТРОКИ НЕОГРАНИЧЕННЫМ ПРЕДШЕСТВУЮЩИМ expr ПРЕДШЕСТВУЮЩИМ ТЕКУЩАЯ СТРОКА expr ПРЕДШЕСТВУЮЩИМ ТЕКУЩАЯ СТРОКА expr СЛЕДУЮЩИМ expr ПРЕДШЕСТВУЮЩИМ ТЕКУЩАЯ СТРОКА expr СЛЕДУЮЩИМ
EXCLUDE CURRENT ROW EXCLUDE GROUP EXCLUDE TIES EXCLUDE NO OTHERS

type-name:

name ( signed-number , signed-number ) ( signed-number )

signed-number:

+ numeric-literal -

ordering-term:

expr COLLATE имя_сортировки DESC ASC NULLS первый NULLS последний

select-core:

ВЫБРАТЬ РАЗЛИЧНЫЕ столбец-результата , ВСЕ ИЗ таблица-или-подзапрос оператор-соединения , ГДЕ выражение СГРУППИРОВАТЬ ПО выражение ПРИ выражение , ОКНО имя-окна КАК определение-окна ,
ЗНАЧЕНИЯ ( expr ) , ,

оператор join:

table-or-subquery join-operator table-or-subquery join-constraint

join-constraint:

USING ( column-name ) , ON expr

join-operator:

NATURAL LEFT OUTER JOIN , RIGHT FULL INNER CROSS

result-column:

expr AS имя_колонки * имя_таблицы . *

таблица или подзапрос:

имя_схемы . имя_таблицы КАК псевдоним_таблицы ИНДЕКСИРОВАНА ПО имя_индекса НЕ ИНДЕКСИРОВАНА имя_функции_таблицы ( выражение ) , КАК псевдоним_таблицы ( выражение_выбора ) ( таблица_или_подзапрос ) ,
join-clause

запрос-выбор:

С РЕКУРСИВНАЯ общее-выражение-с-таблицей , ВЫБЕРИТЕ УНИКАЛЬНЫЕ столбец-результата , ВСЕ ИЗ таблицы-или-подзапроса оператор-соединения , ГДЕ выражение ГРУППИРОВАТЬ ПО выражение ПРИ выражение ,
ОКНО window-name КАК window-defn , ЗНАЧЕНИЯ ( expr ) , , compound-operator select-core ПОРЯДОК ПО ЛИМИТ expr ordering-term , СМЕЩЕНИЕ expr , expr

compound-operator:

UNION UNION INTERSECT EXCEPT ALL

window-defn:

( base-window-name PARTITION BY expr , ORDER BY ordering-term , frame-spec )

frame-spec:

ГРУППЫ МЕЖДУ НЕОГРАНИЧЕННЫХ ПРЕДШЕСТВУЮЩИХ И НЕОГРАНИЧЕННЫХ СЛЕДУЮЩИХ ДИАПАЗОН СТРОК НЕОГРАНИЧЕННЫХ ПРЕДШЕСТВУЮЩИХ expr ПРЕДШЕСТВУЮЩИХ ТЕКУЩЕЙ СТРОКИ expr ПРЕДШЕСТВУЮЩИХ ТЕКУЩЕЙ СТРОКИ expr СЛЕДУЮЩИХ expr ПРЕДШЕСТВУЮЩИХ ТЕКУЩЕЙ СТРОКИ expr СЛЕДУЮЩИХ
ИСКЛЮЧИТЬ ТЕКУЩИЙ РЯД ИСКЛЮЧИТЬ ГРУППА ИСКЛЮЧИТЬ СВЯЗИ ИСКЛЮЧИТЬ НЕТ ДРУГИЕ

В составном запросе SELECT все составляющие запросы SELECT должны возвращать одинаковое количество столбцов результатов. Поскольку компоненты составного запроса SELECT должны быть простыми операторами SELECT, они не могут содержать предложения ORDER BY или LIMIT. Предложения ORDER BY и LIMIT могут встречаться только в конце всего составного запроса SELECT, и только если последний элемент составного запроса не является предложением VALUES.

Составной запрос SELECT, созданный с использованием оператора UNION ALL, возвращает все строки из оператора SELECT слева от оператора UNION ALL и все строки из оператора SELECT справа от него. Оператор UNION работает так же, как UNION ALL, за исключением того, что дублирующиеся строки удаляются из конечного набора результатов. Оператор INTERSECT возвращает пересечение результатов левого и правого запросов SELECT. Оператор EXCEPT возвращает подмножество строк, возвращаемых левым запросом SELECT, которые также не возвращаются правым запросом SELECT. Дублирующиеся строки удаляются из результатов операторов INTERSECT и EXCEPT перед возвращением набора результатов.

В целях определения дублирующихся строк для результатов операторов составных запросов SELECT значения NULL считаются равными другим значениям NULL и отличными от всех значений, отличных от NULL. Последовательность сортировки, используемая для сравнения двух текстовых значений, определяется так, как если бы столбцы левого и правого операторов SELECT были левым и правым операндами оператора равенства (=), за исключением того, что оператору сортировки не присваивается более высокий приоритет, указанный с помощью оператора COLLATE. Никакие преобразования аффинитета не применяются к значениям при сравнении строк в рамках составного запроса SELECT.

Когда три или более простых оператора SELECT соединяются в составной запрос SELECT, они группируются слева направо. Другими словами, если "A", "B" и "C" — все простые операторы SELECT, то (A op B op C) обрабатывается как ((A op B) op C).

4. Предложение ORDER BY

Если оператор SELECT, возвращающий более одной строки, не имеет предложения ORDER BY, порядок возвращения строк не определен. Или, если у оператора SELECT есть предложение ORDER BY, то список выражений, прикрепленных к ORDER BY, определяет порядок возвращения строк пользователю.

В операторе составного запроса SELECT только последний или самый правый простой запрос SELECT может иметь предложение ORDER BY. Это предложение ORDER BY будет применяться ко всем элементам составного запроса. Если правым элементом составного запроса SELECT является предложение VALUES, то предложение ORDER BY для этого оператора не разрешено.

Строки сначала сортируются на основе результатов вычисления самого левого выражения в списке ORDER BY, затем связи разрываются путем вычисления второго самого левого выражения и так далее. Порядок возвращения двух строк, для которых все выражения ORDER BY вычисляются в равных значениях, не определен. За каждым выражением ORDER BY может следовать одно из ключевых слов ASC (меньшие значения возвращаются первыми) или DESC (большие значения возвращаются первыми). Если ни ASC, ни DESC не указаны, строки сортируются по умолчанию в порядке возрастания (меньшие значения сначала).

SQLite рассматривает значения NULL как меньшие, чем любые другие значения для целей сортировки. Следовательно, значения NULL естественным образом появляются в начале ASC-упорядочения и в конце DESC-упорядочения. Это можно изменить, используя синтаксис "ASC NULLS LAST" или "DESC NULLS FIRST".

Каждое выражение ORDER BY обрабатывается следующим образом:

  1. Если выражение ORDER BY является целочисленной константой K, то выражение рассматривается как псевдоним для K-го столбца набора результатов (столбцы нумеруются слева направо, начиная с 1).

  2. Если выражение ORDER BY является идентификатором, соответствующим псевдониму одного из выходных столбцов, то выражение рассматривается как псевдоним для этого столбца.

  3. В противном случае, если выражение ORDER BY — любое другое выражение, оно вычисляется, и возвращаемое значение используется для упорядочения выходных строк. Если оператор SELECT является простым оператором SELECT, то предложение ORDER BY может содержать любые произвольные выражения. Однако, если SELECT является составным запросом SELECT, то выражения ORDER BY, которые не являются псевдонимами выходных столбцов, должны быть точно такими же, как выражение, используемое в качестве выходного столбца.

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

  1. Если выражению ORDER BY присвоена последовательность сортировки с помощью постфикса оператора COLLATE, то используется указанная последовательность сортировки.

  2. В противном случае, если выражение ORDER BY является псевдонимом выражения, которому была присвоена последовательность сортировки с помощью постфикса оператора COLLATE, то используется последовательность сортировки, присвоенная алиасному выражению.

  3. В противном случае, если выражение ORDER BY является столбцом или псевдонимом выражения, являющегося столбцом, то используется последовательность сортировки по умолчанию для столбца.

  4. В противном случае используется последовательность сортировки BINARY.

В операторе составного запроса SELECT все выражения ORDER BY обрабатываются как псевдонимы одного из столбцов результатов составного запроса. Если выражение ORDER BY не является целочисленным псевдонимом, то SQLite ищет в самом левом операторе SELECT столбец результатов, который соответствует либо второму, либо третьему правилам выше. Если совпадение найдено, поиск останавливается, и выражение обрабатывается как псевдоним для столбца результатов, с которым оно сопоставлено. В противном случае пытается следующий оператор SELECT справа, и так далее. Если в столбцах результатов любого составляющего оператора SELECT не может быть найдено совпадающее выражение, это ошибка. Каждый член предложения ORDER BY обрабатывается отдельно и может быть сопоставлен с столбцами результатов разных операторов SELECT в составном запросе.

5. Предложение LIMIT

Оператор LIMIT используется для задания верхнего предела числа строк, возвращаемых полным оператором SELECT.

В составном операторе SELECT только последний или самый правый простой оператор SELECT может содержать оператор LIMIT. В составном операторе SELECT оператор LIMIT применяется ко всему составному оператору, а не только к конечному оператору SELECT. Если самый правый простой оператор SELECT — это оператор VALUES, то оператор LIMIT не допускается.

В операторе LIMIT может использоваться любое скалярное выражение, при условии, что оно вычисляется в целое число или значение, которое может быть без потерь преобразовано в целое число. Если выражение вычисляется в значение NULL или любое другое значение, которое не может быть без потерь преобразовано в целое число, возвращается ошибка. Если выражение LIMIT вычисляется в отрицательное значение, то нет верхнего предела числа возвращаемых строк. В противном случае оператор SELECT возвращает только первые N строк своего набора результатов, где N — значение, вычисленное выражением LIMIT. Или, если оператор SELECT вернул бы меньше N строк без оператора LIMIT, то возвращается весь набор результатов.

Выражение, прикрепленное к необязательному оператору OFFSET, который может следовать за оператором LIMIT, также должно вычисляться в целое число или значение, которое может быть без потерь преобразовано в целое число. Если имеется оператор OFFSET, то из набора результатов, возвращаемого оператором SELECT, пропускаются первые M строк, а затем возвращаются следующие N строк, где M и N — значения, вычисляемые операторами OFFSET и LIMIT соответственно. Или, если оператор SELECT вернул бы меньше M+N строк, если бы он не содержал оператор LIMIT, то пропускаются первые M строк, а затем возвращаются оставшиеся строки (если таковые имеются). Если оператор OFFSET вычисляется в отрицательное значение, результаты такие же, как если бы он был равен нулю.

Вместо отдельного оператора OFFSET оператор LIMIT может указывать два скалярных выражения, разделенных запятой. В этом случае первое выражение используется как выражение OFFSET, а второе — как выражение LIMIT. Это может быть интуитивно нелогично, так как при использовании оператора OFFSET второе из двух выражений является OFFSET, а первое — LIMIT. Это обратное изменение порядка OFFSET и LIMIT преднамеренное — оно максимизирует совместимость с другими системами баз данных SQL. Однако, чтобы избежать путаницы, программистам настоятельно рекомендуется использовать форму оператора LIMIT, которая использует ключевое слово «OFFSET», и избегать использования оператора LIMIT с запятой.

6.Оператор VALUES

Фраза «VALUES(expr-list)» означает то же самое, что и «SELECT expr-list». Фраза «VALUES(expr-list-1),...,(expr-list-N)» означает то же самое, что и «SELECT expr-list-1 UNION ALL ... UNION ALL SELECT expr-list-N». Обе формы одинаковы, за исключением того, что количество операторов SELECT в составном операторе ограничено SQLITE_LIMIT_COMPOUND_SELECT, в то время как количество строк в операторе VALUES не имеет произвольных ограничений.

Существуют некоторые ограничения на использование оператора VALUES, которые не показаны на диаграммах синтаксиса:

  • После оператора VALUES не может следовать ORDER BY.

  • После оператора VALUES не может следовать LIMIT.

7.Оператор WITH

Операторы SELECT могут быть необязательно предваряться одиночным оператором WITH, который определяет один или несколько общих табличных выражений для использования в операторе SELECT.

8. Таблично-значимые функции в предложении FROM

Виртуальная таблица, содержащая скрытые столбцы, может использоваться как таблично-значимая функция в предложении FROM. Аргументы таблично-значимой функции становятся ограничениями для СКРЫТЫХ столбцов виртуальной таблицы. Дополнительную информацию можно найти в документации по виртуальным таблицам.

9. Отклонения от стандарта SQL

Синтаксис SELECT в SQLite незначительно отличается от стандартного SQL. Эти различия обусловлены несколькими причинами:

  • В середине 2000-х годов большое внимание уделялось минимизации объёма библиотеки, чтобы не занимать слишком много места в памяти ограниченных мобильных телефонов и аналогичных устройств.

  • В ранние годы разработки SQLite ведущий разработчик стремился следовать закону Постела и быть снисходительным и гибким в отношении принимаемых входных данных.

  • В ранних парсерах SQLite были ошибки, которые принимали некоторые странные вводные данные.

  • Знания ведущего разработчика о SQL были несовершенными.

Каким бы ни был источник этих особенностей ввода, мы обычно избегаем попыток их "исправить", так как любые новые ограничения на синтаксис ввода, вероятно, приведут к тому, что сломаются по крайней мере некоторые из миллионов приложений, использующих SQLite. Мы этого не хотим. Цель команды разработчиков SQLite – сохранить обратную совместимость в максимальной степени. Поэтому, если ошибка синтаксиса безобидна, мы оставляем её и документируем её здесь, а не пытаемся её исправить.

9.1. Странные имена JOIN

SQLite принимает весь обычный синтаксис для операторов JOIN:

join-operator:

NATURAL LEFT OUTER JOIN ,

Но на этом не заканчивается. SQLite на самом деле очень гибко позволяет указывать оператор соединения. Общий синтаксис:

 blah blah blah JOIN 

В случаях, когда встречается от 1 до 3 вхождений «blah», каждое из которых может быть «CROSS», «FULL», «INNER», «LEFT», «NATURAL», «OUTER» или «RIGHT». Парсер SQLite рассматривает каждое из этих ключевых слов как атрибут соединения, которые могут быть объединены в любом порядке. Это создает возможность многих новых и креативных типов соединений, выходящих за рамки того, что указано в диаграмме синтаксиса. Некоторые из этих нестандартных типов соединений специально запрещены. Например, нельзя сказать «INNER OUTER JOIN», так как это противоречиво. Но можно сказать такие вещи, как «OUTER LEFT NATURAL JOIN», что означает то же, что и «NATURAL LEFT OUTER JOIN». Или можно сказать «LEFT RIGHT JOIN», что равносильно «FULL JOIN».

Запомните: вы можете использовать эти нестандартные типы соединений, но вам не следует. Придерживайтесь стандартного синтаксиса JOIN для совместимости с другими движками баз данных SQL.

9.2. Гибкий синтаксис соединения

Стандартный SQL имеет более строгие ограничения на синтаксис соединения, чем SQLite. В стандартном SQL все соединения, кроме соединений через запятую, CROSS JOIN и NATURAL соединений, должны иметь либо предложение ON, либо предложение USING, а соединения через запятую, CROSS JOIN и NATURAL соединения не должны иметь ни предложения ON, ни USING. SQLite не так требователен к синтаксису соединения. SQLite будет принимать и обрабатывать предложение ON или USING в соединении через запятую или CROSS JOIN и позволит вам опустить предложение ON или USING из любого соединения. В SQLite единственные ограничения:

  • Вы не можете использовать предложение ON или USING в NATURAL соединении.

  • Вы не можете использовать предложения ON и USING в одном и том же соединении.

SQLite даже позволяет опустить предложение ON или USING из внешнего соединения, хотя это означает, что внешнее соединение не ограничено (как будто предложение ON было «ON true»), что заставляет внешнее соединение вести себя как внутреннее соединение.

9.3. Преимущество соединений через запятую и CROSS JOIN

В стандартном SQL соединения, использующие ключевое слово JOIN, имеют более высокий приоритет, чем соединения через запятую. То есть операторы JOIN выполняются до операторов запятой. Это не так в SQLite, где все соединения имеют одинаковый приоритет.

Рассмотрим этот пример:

... FROM t1, t2 NATURAL FULL JOIN t3 ...

В стандартном SQL FULL JOIN между t2 и t3 будет выполняться первым, а затем результат левого соединения будет перекрестно соединён с t1. Но SQLite всегда обрабатывает все соединения слева направо. Таким образом, SQLite сначала выполнит перекрестное соединение t1 и t2, а затем результат этого перекрестного соединения будет подставлен в FULL JOIN с t3. Внутренние соединения изначально ассоциативны, поэтому разница проявляется только в том случае, если предложение FROM содержит одно или несколько внешних соединений.

Вы можете обойти это и сделать ваши SQL-запросы совместимыми со всеми системами, следуя следующим стилистическим правилам:

  • Не смешивайте соединения через запятую с ключевым словом JOIN. Соединения через запятую можно использовать, но если вы их используете, то должны применять только соединения через запятую для всего предложения FROM.

  • Предпочитайте LEFT JOIN другим операторам внешних соединений.

  • В случае сомнений, используйте скобки для указания точного порядка соединений, которые вы хотите.

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

Эта страница была в последний раз изменена 11 мая 2024 г. 12:18:17 UTC

SQLite is in the Public Domain.
https://sqlite.org/lang_select.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API