17 KiB
sidebar_position | sidebar_label |
---|---|
31 | Синтаксис |
Синтаксис
В системе есть два вида парсеров: полноценный парсер SQL (recursive descent parser) и парсер форматов данных (быстрый потоковый парсер). Во всех случаях кроме запроса INSERT, используется только полноценный парсер SQL. В запросе INSERT используется оба парсера:
INSERT INTO t VALUES (1, 'Hello, world'), (2, 'abc'), (3, 'def')
Фрагмент INSERT INTO t VALUES
парсится полноценным парсером, а данные (1, 'Hello, world'), (2, 'abc'), (3, 'def')
- быстрым потоковым парсером.
Данные могут иметь любой формат. При получении запроса, сервер заранее считывает в оперативку не более max_query_size
байт запроса (по умолчанию, 1МБ), а всё остальное обрабатывается потоково.
Таким образом, в системе нет проблем с большими INSERT запросами, как в MySQL.
При использовании формата Values в INSERT запросе может сложиться иллюзия, что данные парсятся также, как выражения в запросе SELECT, но это не так. Формат Values гораздо более ограничен.
Далее пойдёт речь о полноценном парсере. О парсерах форматов, смотри раздел «Форматы».
Пробелы
Между синтаксическими конструкциями (в том числе, в начале и конце запроса) может быть расположено произвольное количество пробельных символов. К пробельным символам относятся пробел, таб, перевод строки, CR, form feed.
Комментарии
Поддерживаются комментарии в SQL-стиле и C-стиле.
Комментарии в SQL-стиле: от --
, #!
или #
до конца строки. Пробел после --
и #!
может не ставиться.
Комментарии в C-стиле: от /*
до */
. Такие комментарии могут быть многострочными. Пробелы тоже не обязательны.
Ключевые слова
Ключевые слова не зависят от регистра, если они соответствуют:
- Стандарту SQL. Например, применение любого из вариантов
SELECT
,select
илиSeLeCt
не вызовет ошибки. - Реализации в некоторых популярных DBMS (MySQL или Postgres). Например,
DateTime
иdatetime
.
Зависимость от регистра для имён типов данных можно проверить в таблице system.data_type_families.
В отличие от стандарта SQL, все остальные ключевые слова, включая названия функций зависят от регистра.
Ключевые слова не зарезервированы (а всего лишь парсятся как ключевые слова в соответствующем контексте). Если вы используете идентификаторы, совпадающие с ключевыми словами, заключите их в кавычки. Например, запрос SELECT "FROM" FROM table_name
валиден, если таблица table_name
имеет столбец с именем "FROM"
.
Идентификаторы
Идентификаторы:
- Имена кластеров, баз данных, таблиц, разделов и столбцов;
- Функции;
- Типы данных;
- Синонимы выражений.
Некоторые идентификаторы нужно указывать в кавычках (например, идентификаторы с пробелами). Прочие идентификаторы можно указывать без кавычек. Рекомендуется использовать идентификаторы, не требующие кавычек.
Идентификаторы не требующие кавычек соответствуют регулярному выражению ^[a-zA-Z_][0-9a-zA-Z_]*$
и не могут совпадать с ключевыми словами. Примеры: x, _1, X_y__Z123_.
Если вы хотите использовать идентификаторы, совпадающие с ключевыми словами, или использовать в идентификаторах символы, не входящие в регулярное выражение, заключите их в двойные или обратные кавычки, например, "id"
, `id`
.
Литералы
Существуют: числовые, строковые, составные литералы и NULL
.
Числовые
Числовой литерал пытается распарситься:
- Сначала как знаковое 64-разрядное число, функцией strtoull.
- Если не получилось, то как беззнаковое 64-разрядное число, функцией strtoll.
- Если не получилось, то как число с плавающей запятой, функцией strtod.
- Иначе — ошибка.
Соответствующее значение будет иметь тип минимального размера, который вмещает значение.
Например, 1 парсится как UInt8
, а 256 как UInt16
. Подробнее о типах данных читайте в разделе Типы данных.
Примеры: 1
, 18446744073709551615
, 0xDEADBEEF
, 01
, 0.1
, 1e100
, -1e-100
, inf
, nan
.
Строковые
Поддерживаются только строковые литералы в одинарных кавычках. Символы внутри могут быть экранированы с помощью обратного слеша. Следующие escape-последовательности имеют соответствующее специальное значение: \b
, \f
, \r
, \n
, \t
, \0
, \a
, \v
, \xHH
. Во всех остальных случаях, последовательности вида \c
, где c
— любой символ, преобразуется в c
. Таким образом, могут быть использованы последовательности \'
и \\
. Значение будет иметь тип String.
Минимальный набор символов, которых вам необходимо экранировать в строковых литералах: '
и \
. Одинарная кавычка может быть экранирована одинарной кавычкой, литералы 'It\'s'
и 'It''s'
эквивалентны.
Составные
Поддерживаются конструкции для массивов: [1, 2, 3]
и кортежей: (1, 'Hello, world!', 2)
.
На самом деле, это вовсе не литералы, а выражение с оператором создания массива и оператором создания кортежа, соответственно.
Массив должен состоять хотя бы из одного элемента, а кортеж - хотя бы из двух.
Кортежи носят служебное значение для использования в секции IN
запроса SELECT
. Кортежи могут быть получены как результат запроса, но они не могут быть сохранены в базе данных (за исключением таблицы Memory.)
NULL
Обозначает, что значение отсутствует.
Чтобы в поле таблицы можно было хранить NULL
, оно должно быть типа Nullable.
В зависимости от формата данных (входных или выходных) NULL
может иметь различное представление. Подробнее смотрите в документации для форматов данных.
При обработке NULL
есть множество особенностей. Например, если хотя бы один из аргументов операции сравнения — NULL
, то результатом такой операции тоже будет NULL
. Этим же свойством обладают операции умножения, сложения и пр. Подробнее читайте в документации на каждую операцию.
В запросах можно проверить NULL
с помощью операторов IS NULL и IS NOT NULL, а также соответствующих функций isNull
и isNotNull
.
Heredoc
Синтаксис heredoc — это способ определения строк с сохранением исходного формата (часто с переносом строки). Heredoc
задается как произвольный строковый литерал между двумя символами $
, например $heredoc$
. Значение между двумя heredoc
обрабатывается "как есть".
Синтаксис heredoc
часто используют для вставки кусков кода SQL, HTML, XML и т.п.
Пример
Запрос:
SELECT $smth$SHOW CREATE VIEW my_view$smth$;
Результат:
┌─'SHOW CREATE VIEW my_view'─┐
│ SHOW CREATE VIEW my_view │
└────────────────────────────┘
Функции
Функции записываются как идентификатор со списком аргументов (возможно, пустым) в скобках. В отличие от стандартного SQL, даже в случае пустого списка аргументов, скобки обязательны. Пример: now()
.
Бывают обычные и агрегатные функции (смотрите раздел «Агрегатные функции»). Некоторые агрегатные функции могут содержать два списка аргументов в круглых скобках. Пример: quantile(0.9)(x)
. Такие агрегатные функции называются «параметрическими», а первый список аргументов называется «параметрами». Синтаксис агрегатных функций без параметров ничем не отличается от обычных функций.
Операторы
Операторы преобразуются в соответствующие им функции во время парсинга запроса, с учётом их приоритета и ассоциативности.
Например, выражение 1 + 2 * 3 + 4
преобразуется в plus(plus(1, multiply(2, 3)), 4)
.
Типы данных и движки таблиц
Типы данных и движки таблиц в запросе CREATE
записываются также, как идентификаторы или также как функции. То есть, могут содержать или не содержать список аргументов в круглых скобках. Подробнее смотрите разделы «Типы данных», «Движки таблиц», «CREATE».
Синонимы выражений
Синоним — это пользовательское имя выражения в запросе.
expr AS alias
-
AS
— ключевое слово для определения синонимов. Можно определить синоним для имени таблицы или столбца в секцииSELECT
без использования ключевого словаAS
.Например, `SELECT table_name_alias.column_name FROM table_name table_name_alias`. В функции [CAST](../sql-reference/syntax.md#type_conversion_function-cast), ключевое слово `AS` имеет другое значение. Смотрите описание функции.
-
expr
— любое выражение, которое поддерживает ClickHouse.Например, `SELECT column_name * 2 AS double FROM some_table`.
-
alias
— имя длявыражения
. Синонимы должны соответствовать синтаксису идентификаторов.Например, `SELECT "table t".column_name FROM table_name AS "table t"`.
Примечания по использованию
Синонимы являются глобальными для запроса или подзапроса, и вы можете определить синоним в любой части запроса для любого выражения. Например, SELECT (1 AS n) + 2, n
.
Синонимы не передаются в подзапросы и между подзапросами. Например, при выполнении запроса SELECT (SELECT sum(b.a) + num FROM b) - a.a AS num FROM a
ClickHouse сгенерирует исключение Unknown identifier: num
.
Если синоним определен для результирующих столбцов в секции SELECT
вложенного запроса, то эти столбцы отображаются во внешнем запросе. Например, SELECT n + m FROM (SELECT 1 AS n, 2 AS m)
.
Будьте осторожны с синонимами, совпадающими с именами столбцов или таблиц. Рассмотрим следующий пример:
CREATE TABLE t
(
a Int,
b Int
)
ENGINE = TinyLog()
SELECT
argMax(a, b),
sum(b) AS b
FROM t
Received exception from server (version 18.14.17):
Code: 184. DB::Exception: Received from localhost:9000, 127.0.0.1. DB::Exception: Aggregate function sum(b) is found inside another aggregate function in query.
В этом примере мы объявили таблицу t
со столбцом b
. Затем, при выборе данных, мы определили синоним sum(b) AS b
. Поскольку синонимы глобальные, то ClickHouse заменил литерал b
в выражении argMax(a, b)
выражением sum(b)
. Эта замена вызвала исключение. Можно изменить это поведение, включив настройку prefer_column_name_to_alias, для этого нужно установить ее в значение 1
.
Звёздочка
В запросе SELECT
, вместо выражения может стоять звёздочка. Подробнее смотрите раздел «SELECT».
Выражения
Выражение представляет собой функцию, идентификатор, литерал, применение оператора, выражение в скобках, подзапрос, звёздочку. А также может содержать синоним. Список выражений - одно выражение или несколько выражений через запятую. Функции и операторы, в свою очередь, в качестве аргументов, могут иметь произвольные выражения.