Синтаксис
В системе есть два вида парсеров: полноценный парсер SQL (recursive descent parser) и парсер форматов данных (быстрый потоковый парсер). Во всех случаях кроме запроса INSERT, используется только полноценный парсер SQL. В запросе INSERT используется оба парсера:
Фрагмент 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 и т.п.
Пример
Запрос:
Результат:
Функции
Функции записываются как идентификатор со списком аргументов (возможно, пустым) в скобках. В отличие от стандартного SQL, даже в случае пустого списка аргументов, скобки обязательны. Пример: now().
Бывают обычные и агрегатные функции (смотрите раздел «Агрегатные функции»). Некоторые агрегатные функции могут содержать два списка аргументов в круглых скобках. Пример: quantile(0.9)(x). Такие агрегатные функции называются «параметрическими», а первый список аргументов называется «параметрами». Синтаксис агрегатных функций без параметров ничем не отличается от обычных функций.
Операторы
Операторы преобразуются в соответствующие им функции во время парсинга запроса, с учётом их приоритета и ассоциативности.
Например, выражение 1 + 2 * 3 + 4 преобразуется в plus(plus(1, multiply(2, 3)), 4).
Типы данных и движки таблиц
Типы данных и движки таблиц в запросе CREATE записываются также, как идентификаторы или также как функции. То есть, могут содержать или не содержать список аргументов в круглых скобках. Подробнее смотрите разделы «Типы данных», «Движки таблиц», «CREATE».
Синонимы выражений
Синоним — это пользовательское имя выражения в запросе.
-
AS— ключевое слово для определения синонимов. Можно определить синоним для имени таблицы или столбца в секцииSELECTбез использования ключевого словаAS.Например,
SELECT table_name_alias.column_name FROM table_name table_name_alias.В функции 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).
Будьте осторожны с синонимами, совпадающими с именами столбцов или таблиц. Рассмотрим следующий пример:
В этом примере мы объявили таблицу t со столбцом b. Затем, при выборе данных, мы определили синоним sum(b) AS b. Поскольку синонимы глобальные, то ClickHouse заменил литерал b в выражении argMax(a, b) выражением sum(b). Эта замена вызвала исключение. Можно изменить это поведение, включив настройку prefer_column_name_to_alias, для этого нужно установить ее в значение 1.
Звёздочка
В запросе SELECT, вместо выражения может стоять звёздочка. Подробнее смотрите раздел «SELECT».
Выражения
Выражение представляет собой функцию, идентификатор, литерал, применение оператора, выражение в скобках, подзапрос, звёздочку. А также может содержать синоним. Список выражений - одно выражение или несколько выражений через запятую. Функции и операторы, в свою очередь, в качестве аргументов, могут иметь произвольные выражения.