Перейти к основному содержимому
Перейти к основному содержимому

Синтаксис

В этом разделе мы рассмотрим синтаксис SQL ClickHouse.
ClickHouse использует синтаксис, основанный на SQL, но предлагает ряд расширений и оптимизаций.

Парсинг запросов

В ClickHouse есть два типа парсеров:

  • Полный SQL парсер (рекурсивный нисходящий парсер).
  • Парсер формата данных (быстрый стрим-парсер).

Полный SQL парсер используется во всех случаях, кроме запроса INSERT, который использует оба парсера.

Давайте рассмотрим следующий запрос:

INSERT INTO t VALUES (1, 'Hello, world'), (2, 'abc'), (3, 'def')

Как уже упоминалось, запрос 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":

SELECT "FROM" FROM table_name

Идентификаторы

Идентификаторы это:

Идентификаторы могут быть как кавычеными, так и некорректованными, хотя предпочтительнее пользоваться некорректованными.

Некорректованные идентификаторы должны соответствовать регулярному выражению ^[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 разбирается как UInt8
  • 256 разбирается как UInt16.

Для получения дополнительной информации смотрите Типы данных.

Подчеркивания _ внутри числовых литералов игнорируются и могут быть использованы для улучшения читаемости.

Следующие числовые литералы поддерживаются:

Числовой литералПримеры
Целые числа1, 10_000_000, 18446744073709551615, 01
Десятичные0.1
Научная нотация1e100, -1e-100
Числа с плавающей точкой123.456, inf, nan
Шестнадцатеричный0xc0fe
Шестнадцатеричная строка, совместимая со стандартом SQLx'c0fe'
Двоичный0b1101
Двоичная строка, совместимая со стандартом SQLb'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 определяется как пользовательский строковый литерал, помещенный между двумя символами $.

Например:

SELECT $heredoc$SHOW CREATE VIEW my_view$heredoc$;

┌─'SHOW CREATE VIEW my_view'─┐
│ SHOW CREATE VIEW my_view   │
└────────────────────────────┘
примечание
  • Значение между двумя 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 - каждый с разным типом данных:

SET param_a = 13;
SET param_b = 'str';
SET param_c = '2022-08-04 18:30:53';
SET param_d = {'10': [11, 12], '13': [14, 15]};

SELECT
   {a: UInt32},
   {b: String},
   {c: DateTime},
   {d: Map(String, Array(UInt8))};

13    str    2022-08-04 18:30:53    {'10':[11,12],'13':[14,15]}
Пример с clickhouse-client

Если вы используете clickhouse-client, параметры указываются как --param_name=value. Например, следующий параметр имеет имя message, и он извлекается как String:

clickhouse-client --param_message='hello' --query="SELECT {message: String}"

hello

Если параметр запроса представляет собой имя базы данных, таблицы, функции или другого идентификатора, используйте Identifier для его типа. Например, следующий запрос возвращает строки из таблицы с именем uk_price_paid:

SET param_mytablename = "uk_price_paid";
SELECT * FROM {mytablename:Identifier};
примечание

Параметры запроса не являются общими текстовыми заменами, которые могут быть использованы в произвольных местах в произвольных SQL запросах.
Они в первую очередь предназначены для работы в операторе SELECT на месте идентификаторов или литералов.

Функции

Вызовы функций записываются как идентификатор с списком аргументов (возможно пустым) в круглых скобках.
В отличие от стандартного SQL, скобки обязательны, даже для пустого списка аргументов.
Например:

now()

Также существуют:

Некоторые агрегатные функции могут содержать два списка аргументов в скобках. Например:

quantile (0.9)(x) 

Эти агрегатные функции называются "параметрическими" функциями,
а аргументы в первом списке называются "параметрами".

примечание

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

Операторы

Операторы преобразуются в соответствующие им функции во время парсинга запроса с учетом их приоритета и ассоциативности.

Например, выражение

1 + 2 * 3 + 4

превращается в

plus(plus(1, multiply(2, 3)), 4)`

Типы данных и движки таблиц базы данных

Типы данных и движки таблиц в запросе CREATE записываются так же, как идентификаторы или функции.
Другими словами, они могут содержать или не содержать список аргументов в скобках.

Для получения дополнительной информации смотрите разделы:

Выражения

Выражение может быть любым из следующего:

  • функция
  • идентификатор
  • литерал
  • применение оператора
  • выражение в скобках
  • подзапрос
  • звездочка

Оно также может содержать псевдоним.

Список выражений — это одно или несколько выражений, отделенных запятыми.
Функции и операторы, в свою очередь, могут иметь выражения в качестве аргументов.

Постоянное выражение — это выражение, результат которого известен во время анализа запроса, т.е. до выполнения.
Например, выражения над литералами являются постоянными выражениями.

Псевдонимы выражений

Псевдоним — это имя, заданное пользователем для выражения в запросе.

expr AS alias

Части синтаксиса выше объяснены ниже.

Часть синтаксисаОписаниеПримерЗаметки
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".

Заметки по использованию

  • Псевдонимы являются глобальными для запроса или подзапроса, и вы можете определить псевдоним в любой части запроса для любого выражения. Например:
SELECT (1 AS n) + 2, n`.
  • Псевдонимы не видны в подзапросах и между подзапросами. Например, при выполнении следующего запроса ClickHouse выдает исключение Unknown identifier: num:
`SELECT (SELECT sum(b.a) + num FROM b) - a.a AS num FROM a`
  • Если псевдоним определен для столбцов результата в операторе 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.