Синтаксис
В этом разделе мы рассмотрим синтаксис SQL в ClickHouse. ClickHouse использует синтаксис, основанный на SQL, но предлагает ряд расширений и оптимизаций.
Разбор запросов
В ClickHouse есть два типа парсеров:
- Полный SQL-парсер (рекурсивный нисходящий парсер).
- Парсер формата данных (быстрый потоковый парсер).
Полный SQL-парсер используется во всех случаях, кроме запроса INSERT, который использует оба парсера.
Рассмотрим следующий запрос:
Как уже упоминалось, запрос INSERT использует оба парсера.
Фрагмент INSERT INTO t VALUES разбирается полным парсером,
а данные (1, 'Hello, world'), (2, 'abc'), (3, 'def') разбираются парсером формата данных, или быстрым потоковым парсером.
Включение полного парсера
Вы также можете включить полный парсер для данных,
используя настройку input_format_values_interpret_expressions.
Когда указанная настройка установлена в 1,
ClickHouse сначала пытается разобрать значения с помощью быстрого потокового парсера.
Если это не удаётся, ClickHouse пытается использовать полный парсер для данных, обрабатывая их как SQL-выражения.
Данные могут быть в любом формате.
При получении запроса сервер помещает в оперативную память не более max_query_size байт запроса
(по умолчанию 1 МБ), а остальная часть обрабатывается потоковым парсером.
Это позволяет избежать проблем с большими INSERT-запросами, который является рекомендуемым способом вставки данных в ClickHouse.
При использовании формата Values в запросе INSERT
может показаться, что данные разбираются так же, как выражения в запросе SELECT, однако это не так.
Формат Values гораздо более ограничен.
Оставшаяся часть этого раздела посвящена полному парсеру.
Дополнительные сведения о парсерах форматов см. в разделе Форматы.
Пробелы
- Между синтаксическими конструкциями (включая начало и конец запроса) может быть произвольное количество пробельных символов.
- К пробельным символам относятся пробел, табуляция, перевод строки, возврат каретки (CR) и разрыв страницы.
Комментарии
ClickHouse поддерживает как комментарии в стиле SQL, так и в стиле C:
- Комментарии в стиле SQL начинаются с
--,#!или#и продолжаются до конца строки. Пробел после--и#!можно опустить. - Комментарии в стиле C записываются между
/*и*/и могут быть многострочными. Пробелы также не требуются.
Ключевые слова
Ключевые слова в ClickHouse могут быть чувствительными к регистру или нечувствительными к регистру в зависимости от контекста.
Ключевые слова нечувствительны к регистру, когда они соответствуют:
- стандарту SQL. Например,
SELECT,selectиSeLeCt— все корректны. - реализации в некоторых популярных СУБД (MySQL или Postgres). Например,
DateTimeто же самое, что иdatetime.
Вы можете проверить, является ли имя типа данных чувствительным к регистру, в таблице system.data_type_families.
В отличие от стандартного SQL, все остальные ключевые слова (включая имена функций) чувствительны к регистру.
Кроме того, ключевые слова не являются зарезервированными. Они рассматриваются как ключевые только в соответствующем контексте. Если вы используете идентификаторы с тем же именем, что и ключевые слова, заключайте их в двойные кавычки или обратные кавычки.
Например, следующий запрос является корректным, если таблица table_name содержит столбец с именем "FROM":
Идентификаторы
Идентификаторы — это:
- Имена кластера, базы данных, таблицы, партиции и столбца.
- Функции.
- Типы данных.
- Псевдонимы выражений.
Идентификаторы могут заключаться в кавычки или быть без кавычек, при этом предпочтителен второй вариант.
Идентификаторы без кавычек должны соответствовать регулярному выражению ^[a-zA-Z_][0-9a-Z_]*$ и не могут совпадать с ключевыми словами.
См. таблицу ниже с примерами корректных и некорректных идентификаторов:
| Корректные идентификаторы | Некорректные идентификаторы |
|---|---|
xyz, _internal, Id_with_underscores_123_ | 1x, tom@gmail.com, äußerst_schön |
Если вы хотите использовать идентификаторы, совпадающие с ключевыми словами, или хотите использовать в идентификаторах другие символы, заключайте их в двойные кавычки или обратные кавычки, например, "id", `id`.
Те же правила экранирования, которые применяются к идентификаторам в кавычках, также применяются к строковым литералам. Подробности см. в разделе String.
Литералы
В ClickHouse литерал — это значение, которое явно задаётся в запросе. Другими словами, это фиксированное значение, которое не изменяется во время выполнения запроса.
Литералы могут быть:
- Строковыми
- Числовыми
- Составными
NULL- Heredocs (пользовательские строковые литералы)
В следующих разделах мы подробно рассмотрим каждый из этих видов.
String
Строковые литералы должны быть заключены в одинарные кавычки. Двойные кавычки не поддерживаются.
Экранирование работает одним из двух способов:
- с использованием предшествующей одинарной кавычки, когда символ одинарной кавычки
'(и только этот символ) может быть экранирован как'', или - с использованием предшествующего обратного слэша с поддерживаемыми управляющими последовательностями, перечисленными в таблице ниже.
Обратный слэш теряет своё специальное значение, то есть интерпретируется буквально, если он стоит перед символами, отличными от перечисленных ниже.
| Supported Escape | Description |
|---|---|
\xHH | 8-битный символ, за которым следует любое количество шестнадцатеричных цифр (H). |
\N | зарезервировано, ничего не делает (например, SELECT 'a\Nb' возвращает ab) |
\a | звуковой сигнал |
\b | backspace |
\e | управляющий символ Escape |
\f | перевод страницы |
\n | перевод строки |
\r | возврат каретки |
\t | горизонтальная табуляция |
\v | вертикальная табуляция |
\0 | нулевой символ |
\\ | обратный слэш |
\' (или '') | одинарная кавычка |
\" | двойная кавычка |
` | обратная кавычка (backtick) |
\/ | косая черта (forward slash) |
\= | знак равенства |
| ASCII control characters (c <= 31). | управляющие символы ASCII (c <= 31). |
В строковых литералах необходимо как минимум экранировать символы ' и \, используя управляющие последовательности \' (или: '') и \\.
Числовые литералы
Числовые литералы разбираются следующим образом:
- Если литерал начинается со знака минус
-, этот токен пропускается, а знак результата меняется после разбора. - Числовой литерал сначала разбирается как 64-битное беззнаковое целое число с использованием функции strtoull.
- Если значение имеет префикс
0bили0x/0X, число разбирается как двоичное или шестнадцатеричное соответственно. - Если значение отрицательное и абсолютная величина больше 263, возвращается ошибка.
- Если значение имеет префикс
- Если разбор не удался, значение далее разбирается как число с плавающей запятой с использованием функции strtod.
- В противном случае возвращается ошибка.
Литералы приводятся к наименьшему типу, в который это значение помещается. Например:
1разбирается какUInt8256разбирается какUInt16.
Целочисленные значения шире 64 бит (UInt128, Int128, UInt256, Int256) должны быть явно приведены к более крупному типу, чтобы быть корректно разобраны:
Это обходит описанный выше алгоритм и выполняет разбор целого числа с помощью функции, поддерживающей произвольную точность.
В противном случае литерал будет разобран как число с плавающей запятой и, следовательно, может привести к потере точности из‑за усечения.
Дополнительные сведения см. в разделе Data types.
Символы подчеркивания _ внутри числовых литералов игнорируются и могут использоваться для улучшения читаемости.
Поддерживаются следующие числовые литералы:
| Числовой литерал | Примеры |
|---|---|
| Целые числа | 1, 10_000_000, 18446744073709551615, 01 |
| Десятичные дроби | 0.1 |
| Экспоненциальная запись | 1e100, -1e-100 |
| Числа с плавающей запятой | 123.456, inf, nan |
| Шестнадцатеричные числа | 0xc0fe |
| Строки в шестнадцатеричном формате, совместимые со стандартом SQL | x'c0fe' |
| Двоичные числа | 0b1101 |
| Строки в двоичном формате, совместимые со стандартом SQL | b'1101' |
Восьмеричные литералы не поддерживаются, чтобы избежать случайных ошибок интерпретации.
Составные
Массивы создаются с помощью квадратных скобок [1, 2, 3]. Кортежи создаются с помощью круглых скобок (1, 'Hello, world!', 2).
Технически это не литералы, а выражения с оператором создания массива и оператором создания кортежа соответственно.
Массив должен состоять как минимум из одного элемента, а кортеж — как минимум из двух элементов.
Существует отдельный случай, когда кортежи используются в условии IN запроса SELECT.
Результаты запроса могут включать кортежи, но кортежи не могут храниться в базе данных (за исключением таблиц, использующих движок Memory).
NULL
NULL используется для обозначения отсутствующего значения.
Чтобы хранить NULL в поле таблицы, это поле должно иметь тип Nullable.
Следует учитывать следующее о NULL:
- В зависимости от формата данных (входного или выходного)
NULLможет иметь разное представление. Дополнительную информацию см. в разделе форматы данных. - Обработка
NULLимеет особенности. Например, если хотя бы один из аргументов операции сравнения равенNULL, результат этой операции также будетNULL. То же касается умножения, сложения и других операций. Рекомендуем ознакомиться с документацией для каждой операции. - В запросах вы можете проверять
NULLс помощью операторовIS NULLиIS NOT NULL, а также соответствующих функцийisNullиisNotNull.
Heredoc
Heredoc — это способ задать строку (часто многострочную), сохраняя исходное форматирование.
Heredoc — это пользовательский строковый литерал, помещённый между двумя символами $.
Например:
- Содержимое между двумя heredoc-блоками обрабатывается «как есть».
- Вы можете использовать heredoc, чтобы вставлять фрагменты кода на SQL, HTML, XML и т. д.
Определение и использование параметров запроса
Параметры запроса позволяют писать универсальные запросы, содержащие абстрактные placeholders вместо конкретных идентификаторов. Когда выполняется запрос с параметрами запроса, все placeholders обрабатываются и заменяются фактическими значениями параметров запроса.
Существует два способа задать параметр запроса:
SET param_<name>=<value>--param_<name>='<value>'
Во втором варианте он передаётся как аргумент в clickhouse-client в командной строке, где:
<name>— имя параметра запроса.<value>— его значение.
На параметр запроса можно сослаться в запросе с помощью {<name>: <datatype>}, где <name> — имя параметра запроса, а <datatype> — тип данных, к которому он приводится.
Пример с командой SET
Например, следующий SQL задаёт параметры с именами a, b, c и d, каждый со своим типом данных:
Пример с clickhouse-client
Если вы используете clickhouse-client, параметры указываются как --param_name=value. Например, следующий параметр имеет имя message, и он интерпретируется как значение типа String:
Если параметр запроса представляет имя базы данных, таблицы, функции или другого идентификатора, используйте тип Identifier. Например, следующий запрос возвращает строки из таблицы с именем uk_price_paid:
Параметры запроса не являются универсальным механизмом текстовой подстановки, который можно использовать в произвольных местах произвольных SQL-запросов.
Они в первую очередь предназначены для работы в операторах SELECT вместо идентификаторов или литералов.
Функции
Вызовы функций записываются как идентификатор со списком аргументов (возможно, пустым) в круглых скобках. В отличие от стандартного SQL, скобки обязательны даже для пустого списка аргументов. Например:
Также есть:
Некоторые агрегатные функции могут иметь два списка аргументов в скобках. Например:
Эти агрегатные функции называются параметрическими функциями, а аргументы из первого списка — параметрами.
Синтаксис агрегатных функций без параметров совпадает с синтаксисом обычных функций.
Операторы
Операторы во время разбора запроса преобразуются в соответствующие функции с учётом их приоритета и ассоциативности.
Например, выражение
преобразуется в
Типы данных и движки таблиц базы данных
Типы данных и движки таблиц в запросе CREATE указываются так же, как идентификаторы или функции.
Другими словами, они могут как содержать список аргументов в скобках, так и не содержать его.
Для получения дополнительной информации см. разделы:
Expressions
Выражением может быть любой из следующих типов:
- функция
- идентификатор
- литерал
- применение оператора
- выражение в скобках
- подзапрос
- звёздочка (
*)
Оно также может содержать псевдоним.
Список выражений — это одно или несколько выражений, разделённых запятыми. Функции и операторы, в свою очередь, могут иметь выражения в качестве аргументов.
Константное выражение — это выражение, результат которого известен во время анализа запроса, то есть до выполнения. Например, выражения, состоящие из литералов, являются константными выражениями.
Псевдонимы выражений
Псевдоним — это определяемое пользователем имя для выражения в запросе.
Части приведённого выше синтаксиса описаны ниже.
| Элемент синтаксиса | Описание | Пример | Примечания |
|---|---|---|---|
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 | Имя для expr. Псевдонимы должны соответствовать синтаксису идентификаторов. | SELECT "table t".column_name FROM table_name AS "table t". |
Примечания по использованию
- Псевдонимы действуют в пределах всего запроса или подзапроса, и вы можете задать псевдоним в любой части запроса для любого выражения. Например:
- Псевдонимы не видны в подзапросах и между подзапросами. Например, при выполнении следующего запроса ClickHouse выдаёт исключение
Unknown identifier: num:
- Если для результирующих столбцов в предложении
SELECTподзапроса определены псевдонимы, эти столбцы доступны во внешнем запросе. Например:
- Будьте осторожны с псевдонимами, совпадающими с именами столбцов или таблиц. Рассмотрим следующий пример:
В предыдущем примере мы объявили таблицу t со столбцом b.
Затем при выборке данных мы задали псевдоним sum(b) AS b.
Поскольку псевдонимы являются глобальными,
ClickHouse заменил литерал b в выражении argMax(a, b) выражением sum(b).
Эта замена привела к возникновению исключения.
Вы можете изменить это поведение по умолчанию, установив prefer_column_name_to_alias в значение 1.
Звёздочка
В запросе SELECT звёздочка может использоваться вместо выражения.
Дополнительные сведения см. в разделе SELECT.