Skip to main content

Синтаксис

В системе есть два вида парсеров: полноценный парсер 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](/docs/ru/sql-reference/syntax#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».

Выражения

Выражение представляет собой функцию, идентификатор, литерал, применение оператора, выражение в скобках, подзапрос, звёздочку. А также может содержать синоним. Список выражений - одно выражение или несколько выражений через запятую. Функции и операторы, в свою очередь, в качестве аргументов, могут иметь произвольные выражения.