ВЫБОР
Содержание
1. Обзор
Запрос SELECT используется для запроса базы данных. Результат SELECT — это ноль или более строк данных, где каждая строка имеет фиксированное количество столбцов. Запрос SELECT не вносит никаких изменений в базу данных.
Диаграмма синтаксиса "select-stmt" выше пытается показать как можно больше синтаксиса запроса SELECT в одной диаграмме, потому что некоторые читатели считают это полезным. Следующая диаграмма синтаксиса "factored-select-stmt" является альтернативным синтаксисом, который выражает тот же синтаксис, но пытается разбить синтаксис на более мелкие части.
Обратите внимание, что есть пути по диаграммам синтаксиса, которые не допускаются на практике. Некоторые примеры:
- Оператор 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.
END_OF_DOCUMENT_MARKERПроцесс генерации результатов простого оператора SELECT представлен в описании ниже в четырёх шагах:
-
Обработка предложения FROM: Определяются входные данные для простого оператора SELECT. Входные данные — либо неявный единственный ряд с 0 столбцами (если предложение FROM отсутствует), либо определяемые предложением FROM.
-
Обработка предложения WHERE: Входные данные фильтруются с помощью выражения предложения WHERE.
-
Обработка GROUP BY, HAVING и выражений столбцов результата: Множество строк результата вычисляется путём агрегирования данных в соответствии с любым предложением GROUP BY и вычисления выражений результата для строк отфильтрованных входных данных.
-
Обработка ключевых слов 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():
-
Если одинаковое минимальное или максимальное значение встречается в двух или более строках, то базовые значения могут быть выбраны из любой из этих строк. Выбор произвольный. Нет способа предсказать, из какой строки будут выбраны базовые значения. Выбор может отличаться для разных базовых столбцов в одном и том же запросе.
-
Если в запросе присутствует два или более агрегата min() или max(), то значения базовых столбцов будут взяты из одной из строк, в которой один из агрегатов имеет минимальное или максимальное значение. Выбор того, какой агрегат min() или max() определяет выбор значений базовых столбцов, произвольный. Выбор может отличаться для разных базовых столбцов в одном и том же запросе.
-
Это специальная обработка для агрегатов 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, как показано на следующей диаграмме:
В составном запросе 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 обрабатывается следующим образом:
Если выражение ORDER BY является целочисленной константой K, то выражение рассматривается как псевдоним для K-го столбца набора результатов (столбцы нумеруются слева направо, начиная с 1).
Если выражение ORDER BY является идентификатором, соответствующим псевдониму одного из выходных столбцов, то выражение рассматривается как псевдоним для этого столбца.
В противном случае, если выражение ORDER BY — любое другое выражение, оно вычисляется, и возвращаемое значение используется для упорядочения выходных строк. Если оператор SELECT является простым оператором SELECT, то предложение ORDER BY может содержать любые произвольные выражения. Однако, если SELECT является составным запросом SELECT, то выражения ORDER BY, которые не являются псевдонимами выходных столбцов, должны быть точно такими же, как выражение, используемое в качестве выходного столбца.
В целях сортировки строк значения сравниваются так же, как и для выражений сравнения. Последовательность сортировки, используемая для сравнения двух текстовых значений, определяется следующим образом:
Если выражению ORDER BY присвоена последовательность сортировки с помощью постфикса оператора COLLATE, то используется указанная последовательность сортировки.
В противном случае, если выражение ORDER BY является псевдонимом выражения, которому была присвоена последовательность сортировки с помощью постфикса оператора COLLATE, то используется последовательность сортировки, присвоенная алиасному выражению.
В противном случае, если выражение ORDER BY является столбцом или псевдонимом выражения, являющегося столбцом, то используется последовательность сортировки по умолчанию для столбца.
В противном случае используется последовательность сортировки 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:
Но на этом не заканчивается. 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