Синтаксис
В этом разделе мы рассмотрим синтаксис 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 имеет гораздо более ограниченные возможности.
Остальная часть этого раздела охватывает полный парсер.
Для получения дополнительной информации о парсерах формата, смотрите раздел Форматы.
Пробелы
- Между синтаксическими конструкциями (включая начало и конец запроса) может быть любое количество пробельных символов.
- Пробелы включают пробел, табуляцию, перевод строки, возврат каретки и подачу формы.
Комментарии
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`.
Те же правила, которые применяются к экранированию в цитируемых идентификаторах, также применимы к строковым литералам. Смотрите Строка для получения более подробной информации.
Литералы
В ClickHouse литералом является значение, которое непосредственно представлено в запросе.
Другими словами, это фиксированное значение, которое не изменяется во время выполнения запроса.
Литералы могут быть:
Мы подробно рассмотрим каждую из этих категорий в следующих разделах.
Строка
Строковые литералы должны быть заключены в одинарные кавычки. Двойные кавычки не поддерживаются.
Экранирование работает следующим образом:
- с использованием предшествующей одинарной кавычки, где символ одинарной кавычки
'(и только этот символ) может быть экранирован как'', или - с использованием предшествующего обратного слэша с последующими поддерживаемыми экранированными последовательностями, перечисленными в таблице ниже.
Обратный слэш теряет свое специальное значение, т.е. он интерпретируется буквально, если он предшествует символам, отличным от перечисленных ниже.
| Поддерживаемое экранирование | Описание |
|---|---|
\xHH | Спецификация 8-битного символа, за которой следует любое количество шестнадцатеричных цифр (H). |
\N | зарезервировано, ничего не делает (например, SELECT 'a\Nb' возвращает ab) |
\a | сигнал |
\b | символ возврата |
\e | символ экранирования |
\f | подача формы |
\n | перевод строки |
\r | возврат каретки |
\t | горизонтальная табуляция |
\v | вертикальная табуляция |
\0 | символ нуля |
\\ | обратный слэш |
\' (или '') | одинарная кавычка |
\" | двойная кавычка |
` | обратная кавычка |
\/ | косая черта |
\= | знак равенства |
| Символы управления ASCII (c <= 31). |
В строковых литералах вам необходимо экранировать как минимум ' и \ используя экранированные коды \' (или: '') и \\.
Числовой
Числовые литералы разбираются следующим образом:
- Сначала как 64-битное знаковое число с использованием функции strtoull.
- Если не удалось, как 64-битное беззнаковое число с использованием функции strtoll.
- Если не удалось, как число с плавающей запятой с использованием функции strtod.
- В противном случае возвращается ошибка.
Литеральные значения преобразуются в наименьший тип, в который они помещаются.
Например:
1разбирается какUInt8256разбирается какUInt16.
Для получения дополнительной информации смотрите Типы данных.
Подчеркивания _ внутри числовых литералов игнорируются и могут быть использованы для улучшения читаемости.
Следующие числовые литералы поддерживаются:
| Числовой литерал | Примеры |
|---|---|
| Целые числа | 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.