Синтаксис
В этом разделе мы рассмотрим синтаксис 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 гораздо более ограничен.
В остальной части этого раздела рассматривается полный парсер.
Дополнительную информацию о парсерах форматов см. в разделе Форматы.
Пробельные символы
- Между синтаксическими конструкциями (включая начало и конец запроса) может находиться любое количество пробельных символов.
- К пробельным символам относятся: пробел, табуляция, перевод строки (LF), возврат каретки (CR) и перевод страницы (FF).
Комментарии
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-zA-Z_]*$ и не могут совпадать с ключевыми словами.
Примеры допустимых и недопустимых идентификаторов приведены в таблице ниже:
| Допустимые идентификаторы | Недопустимые идентификаторы |
|---|---|
xyz, _internal, Id_with_underscores_123_ | 1x, tom@gmail.com, äußerst_schön |
Если вы хотите использовать идентификаторы, совпадающие с ключевыми словами, или использовать в идентификаторах другие символы, заключите их в двойные кавычки или обратные апострофы, например: "id", `id`.
Правила экранирования для идентификаторов в кавычках также применяются к строковым литералам. Подробнее см. в разделе String.
Литералы
В ClickHouse литерал — это значение, которое непосредственно представлено в запросе. Другими словами, это фиксированное значение, которое не изменяется во время выполнения запроса.
Литералы могут быть:
Рассмотрим каждый из них более подробно в разделах ниже.
Строковые
Строковые литералы должны быть заключены в одинарные кавычки. Двойные кавычки не поддерживаются.
Экранирование работает одним из следующих способов:
- использование предшествующей одинарной кавычки, где символ одинарной кавычки
'(и только этот символ) может быть экранирован как'', или - использование предшествующей обратной косой черты со следующими поддерживаемыми escape-последовательностями, перечисленными в таблице ниже.
Обратная косая черта теряет свое специальное значение, т.е. интерпретируется буквально, если она предшествует символам, отличным от перечисленных ниже.
| Поддерживаемая escape-последовательность | Описание |
|---|---|
\xHH | Спецификация 8-битного символа, за которой следует любое количество шестнадцатеричных цифр (H). |
\N | зарезервировано, ничего не делает (например, SELECT 'a\Nb' возвращает ab) |
\a | сигнал |
\b | возврат на один символ |
\e | символ escape |
\f | перевод страницы |
\n | перевод строки |
\r | возврат каретки |
\t | горизонтальная табуляция |
\v | вертикальная табуляция |
\0 | нулевой символ |
\\ | обратная косая черта |
\' (или '') | одинарная кавычка |
\" | двойная кавычка |
` | обратная кавычка |
\/ | прямая косая черта |
\= | знак равенства |
| Управляющие символы ASCII (c <= 31). |
В строковых литералах необходимо экранировать как минимум ' и \ с помощью escape-кодов \' (или: '') и \\.
Числовые
Числовые литералы разбираются следующим образом:
- Если литерал имеет префикс в виде знака минус
-, токен пропускается, и результат инвертируется после разбора. - Числовой литерал сначала разбирается как 64-битное беззнаковое целое число с использованием функции strtoull.
- Если значение имеет префикс
0bили0x/0X, число разбирается как двоичное или шестнадцатеричное соответственно. - Если значение отрицательное и абсолютная величина больше 263, возвращается ошибка.
- Если значение имеет префикс
- Если это не удается, значение затем разбирается как число с плавающей точкой с использованием функции strtod.
- В противном случае возвращается ошибка.
Литеральные значения приводятся к наименьшему типу, в который помещается значение. Например:
1разбирается какUInt8256разбирается какUInt16.
Целочисленные значения шире 64 бит (UInt128, Int128, UInt256, Int256) должны быть приведены к более широкому типу для правильного разбора:
Это обходит вышеуказанный алгоритм и разбирает целое число с помощью процедуры, поддерживающей произвольную точность.
В противном случае литерал будет разобран как число с плавающей точкой и, следовательно, подвержен потере точности из-за усечения.
Для получения дополнительной информации см. Типы данных.
Символы подчеркивания _ внутри числовых литералов игнорируются и могут использоваться для улучшения читаемости.
Поддерживаются следующие числовые литералы:
| Числовой литерал | Примеры |
|---|---|
| Целые числа | 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 и т. д.
Определение и использование параметров запроса
Параметры запроса позволяют писать универсальные запросы, содержащие абстрактные заполнители вместо конкретных идентификаторов. При выполнении запроса с параметрами все заполнители разрешаются и заменяются фактическими значениями параметров запроса.
Существует два способа определения параметра запроса:
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 записываются так же, как идентификаторы или функции.
Иными словами, они могут содержать или не содержать список аргументов в скобках.
Дополнительную информацию см. в разделах:
Выражения
Выражением может быть любое из следующего:
- функция
- идентификатор
- литерал
- применение оператора
- выражение в скобках
- подзапрос
- звёздочка
Выражение также может содержать псевдоним.
Список выражений — это одно или несколько выражений, разделённых запятыми. Функции и операторы, в свою очередь, могут принимать выражения в качестве аргументов.
Константное выражение — это выражение, результат которого известен на этапе анализа запроса, т. е. до его выполнения. Например, выражения над литералами являются константными выражениями.
Псевдонимы выражений
Псевдоним — это определяемое пользователем имя для выражения в запросе.
Элементы синтаксиса, приведенного выше, описаны ниже.
| Элемент синтаксиса | Описание | Пример | Примечания |
|---|---|---|---|
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.