mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-30 11:32:03 +00:00
51d4e4d307
Co-authored-by: olgarev <56617294+olgarev@users.noreply.github.com>
183 lines
16 KiB
Markdown
183 lines
16 KiB
Markdown
---
|
||
toc_priority: 31
|
||
toc_title: "Синтаксис"
|
||
---
|
||
|
||
# Синтаксис {#sintaksis}
|
||
|
||
В системе есть два вида парсеров: полноценный парсер SQL (recursive descent parser) и парсер форматов данных (быстрый потоковый парсер).
|
||
Во всех случаях кроме запроса INSERT, используется только полноценный парсер SQL.
|
||
В запросе INSERT используется оба парсера:
|
||
|
||
``` sql
|
||
INSERT INTO t VALUES (1, 'Hello, world'), (2, 'abc'), (3, 'def')
|
||
```
|
||
|
||
Фрагмент `INSERT INTO t VALUES` парсится полноценным парсером, а данные `(1, 'Hello, world'), (2, 'abc'), (3, 'def')` - быстрым потоковым парсером.
|
||
Данные могут иметь любой формат. При получении запроса, сервер заранее считывает в оперативку не более `max_query_size` байт запроса (по умолчанию, 1МБ), а всё остальное обрабатывается потоково.
|
||
Таким образом, в системе нет проблем с большими INSERT запросами, как в MySQL.
|
||
|
||
При использовании формата Values в INSERT запросе может сложиться иллюзия, что данные парсятся также, как выражения в запросе SELECT, но это не так. Формат Values гораздо более ограничен.
|
||
|
||
Далее пойдёт речь о полноценном парсере. О парсерах форматов, смотри раздел «Форматы».
|
||
|
||
## Пробелы {#probely}
|
||
|
||
Между синтаксическими конструкциями (в том числе, в начале и конце запроса) может быть расположено произвольное количество пробельных символов. К пробельным символам относятся пробел, таб, перевод строки, CR, form feed.
|
||
|
||
## Комментарии {#kommentarii}
|
||
|
||
Поддерживаются комментарии в SQL-стиле и C-стиле.
|
||
Комментарии в SQL-стиле: от `--` до конца строки. Пробел после `--` может не ставиться.
|
||
Комментарии в C-стиле: от `/*` до `*/`. Такие комментарии могут быть многострочными. Пробелы тоже не обязательны.
|
||
|
||
## Ключевые слова {#syntax-keywords}
|
||
|
||
Ключевые слова не зависят от регистра, если они соответствуют:
|
||
|
||
- Стандарту SQL. Например, применение любого из вариантов `SELECT`, `select` или `SeLeCt` не вызовет ошибки.
|
||
- Реализации в некоторых популярных DBMS (MySQL или Postgres). Например, `DateTime` и `datetime`.
|
||
|
||
Зависимость от регистра для имён типов данных можно проверить в таблице [system.data_type_families](../operations/system-tables/data_type_families.md#system_tables-data_type_families).
|
||
|
||
В отличие от стандарта SQL, все остальные ключевые слова, включая названия функций зависят от регистра.
|
||
|
||
Ключевые слова не зарезервированы (а всего лишь парсятся как ключевые слова в соответствующем контексте). Если вы используете [идентификаторы](#syntax-identifiers), совпадающие с ключевыми словами, заключите их в кавычки. Например, запрос `SELECT "FROM" FROM table_name` валиден, если таблица `table_name` имеет столбец с именем `"FROM"`.
|
||
|
||
## Идентификаторы {#syntax-identifiers}
|
||
|
||
Идентификаторы:
|
||
|
||
- Имена кластеров, баз данных, таблиц, разделов и столбцов;
|
||
- Функции;
|
||
- Типы данных;
|
||
- [Синонимы выражений](#syntax-expression_aliases).
|
||
|
||
Некоторые идентификаторы нужно указывать в кавычках (например, идентификаторы с пробелами). Прочие идентификаторы можно указывать без кавычек. Рекомендуется использовать идентификаторы, не требующие кавычек.
|
||
|
||
Идентификаторы не требующие кавычек соответствуют регулярному выражению `^[a-zA-Z_][0-9a-zA-Z_]*$` и не могут совпадать с [ключевыми словами](#syntax-keywords). Примеры: `x, _1, X_y__Z123_.`
|
||
|
||
Если вы хотите использовать идентификаторы, совпадающие с ключевыми словами, или использовать в идентификаторах символы, не входящие в регулярное выражение, заключите их в двойные или обратные кавычки, например, `"id"`, `` `id` ``.
|
||
|
||
## Литералы {#literals}
|
||
|
||
Существуют: числовые, строковые, составные литералы и `NULL`.
|
||
|
||
### Числовые {#chislovye}
|
||
|
||
Числовой литерал пытается распарситься:
|
||
|
||
- Сначала как знаковое 64-разрядное число, функцией [strtoull](https://en.cppreference.com/w/cpp/string/byte/strtoul).
|
||
- Если не получилось, то как беззнаковое 64-разрядное число, функцией [strtoll](https://en.cppreference.com/w/cpp/string/byte/strtol).
|
||
- Если не получилось, то как число с плавающей запятой, функцией [strtod](https://en.cppreference.com/w/cpp/string/byte/strtof).
|
||
- Иначе — ошибка.
|
||
|
||
Соответствующее значение будет иметь тип минимального размера, который вмещает значение.
|
||
Например, 1 парсится как `UInt8`, а 256 как `UInt16`. Подробнее о типах данных читайте в разделе [Типы данных](../sql-reference/syntax.md).
|
||
|
||
Примеры: `1`, `18446744073709551615`, `0xDEADBEEF`, `01`, `0.1`, `1e100`, `-1e-100`, `inf`, `nan`.
|
||
|
||
### Строковые {#syntax-string-literal}
|
||
|
||
Поддерживаются только строковые литералы в одинарных кавычках. Символы внутри могут быть экранированы с помощью обратного слеша. Следующие escape-последовательности имеют соответствующее специальное значение: `\b`, `\f`, `\r`, `\n`, `\t`, `\0`, `\a`, `\v`, `\xHH`. Во всех остальных случаях, последовательности вида `\c`, где `c` — любой символ, преобразуется в `c` . Таким образом, могут быть использованы последовательности `\'` и `\\`. Значение будет иметь тип [String](../sql-reference/syntax.md).
|
||
|
||
Минимальный набор символов, которых вам необходимо экранировать в строковых литералах: `'` и `\`. Одинарная кавычка может быть экранирована одинарной кавычкой, литералы `'It\'s'` и `'It''s'` эквивалентны.
|
||
|
||
### Составные {#sostavnye}
|
||
|
||
Поддерживаются конструкции для массивов: `[1, 2, 3]` и кортежей: `(1, 'Hello, world!', 2)`.
|
||
На самом деле, это вовсе не литералы, а выражение с оператором создания массива и оператором создания кортежа, соответственно.
|
||
Массив должен состоять хотя бы из одного элемента, а кортеж - хотя бы из двух.
|
||
Кортежи носят служебное значение для использования в секции `IN` запроса `SELECT`. Кортежи могут быть получены как результат запроса, но они не могут быть сохранены в базе данных (за исключением таблицы [Memory](../sql-reference/syntax.md).)
|
||
|
||
### NULL {#null-literal}
|
||
|
||
Обозначает, что значение отсутствует.
|
||
|
||
Чтобы в поле таблицы можно было хранить `NULL`, оно должно быть типа [Nullable](../sql-reference/syntax.md).
|
||
|
||
В зависимости от формата данных (входных или выходных) `NULL` может иметь различное представление. Подробнее смотрите в документации для [форматов данных](../interfaces/formats.md#formats).
|
||
|
||
При обработке `NULL` есть множество особенностей. Например, если хотя бы один из аргументов операции сравнения — `NULL`, то результатом такой операции тоже будет `NULL`. Этим же свойством обладают операции умножения, сложения и пр. Подробнее читайте в документации на каждую операцию.
|
||
|
||
В запросах можно проверить `NULL` с помощью операторов [IS NULL](operators/index.md#operator-is-null) и [IS NOT NULL](operators/index.md), а также соответствующих функций `isNull` и `isNotNull`.
|
||
|
||
## Функции {#funktsii}
|
||
|
||
Функции записываются как идентификатор со списком аргументов (возможно, пустым) в скобках. В отличие от стандартного SQL, даже в случае пустого списка аргументов, скобки обязательны. Пример: `now()`.
|
||
Бывают обычные и агрегатные функции (смотрите раздел «Агрегатные функции»). Некоторые агрегатные функции могут содержать два списка аргументов в круглых скобках. Пример: `quantile(0.9)(x)`. Такие агрегатные функции называются «параметрическими», а первый список аргументов называется «параметрами». Синтаксис агрегатных функций без параметров ничем не отличается от обычных функций.
|
||
|
||
## Операторы {#operatory}
|
||
|
||
Операторы преобразуются в соответствующие им функции во время парсинга запроса, с учётом их приоритета и ассоциативности.
|
||
Например, выражение `1 + 2 * 3 + 4` преобразуется в `plus(plus(1, multiply(2, 3)), 4)`.
|
||
|
||
## Типы данных и движки таблиц {#tipy-dannykh-i-dvizhki-tablits}
|
||
|
||
Типы данных и движки таблиц в запросе `CREATE` записываются также, как идентификаторы или также как функции. То есть, могут содержать или не содержать список аргументов в круглых скобках. Подробнее смотрите разделы «Типы данных», «Движки таблиц», «CREATE».
|
||
|
||
## Синонимы выражений {#syntax-expression_aliases}
|
||
|
||
Синоним — это пользовательское имя выражения в запросе.
|
||
|
||
``` sql
|
||
expr AS alias
|
||
```
|
||
|
||
- `AS` — ключевое слово для определения синонимов. Можно определить синоним для имени таблицы или столбца в секции `SELECT` без использования ключевого слова `AS` .
|
||
|
||
Например, `SELECT table_name_alias.column_name FROM table_name table_name_alias`.
|
||
|
||
В функции [CAST](../sql_reference/syntax.md#type_conversion_function-cast), ключевое слово `AS` имеет другое значение. Смотрите описание функции.
|
||
|
||
- `expr` — любое выражение, которое поддерживает ClickHouse.
|
||
|
||
Например, `SELECT column_name * 2 AS double FROM some_table`.
|
||
|
||
- `alias` — имя для `выражения`. Синонимы должны соответствовать синтаксису [идентификаторов](#syntax-identifiers).
|
||
|
||
Например, `SELECT "table t".column_name FROM table_name AS "table t"`.
|
||
|
||
### Примечания по использованию {#notes-on-usage}
|
||
|
||
Синонимы являются глобальными для запроса или подзапроса, и вы можете определить синоним в любой части запроса для любого выражения. Например, `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)`.
|
||
|
||
Будьте осторожны с синонимами, совпадающими с именами столбцов или таблиц. Рассмотрим следующий пример:
|
||
|
||
``` sql
|
||
CREATE TABLE t
|
||
(
|
||
a Int,
|
||
b Int
|
||
)
|
||
ENGINE = TinyLog()
|
||
```
|
||
|
||
``` sql
|
||
SELECT
|
||
argMax(a, b),
|
||
sum(b) AS b
|
||
FROM t
|
||
```
|
||
|
||
``` text
|
||
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](../operations/settings/settings.md#prefer_column_name_to_alias), для этого нужно установить ее в значение `1`.
|
||
|
||
## Звёздочка {#asterisk}
|
||
|
||
В запросе `SELECT`, вместо выражения может стоять звёздочка. Подробнее смотрите раздел «SELECT».
|
||
|
||
## Выражения {#syntax-expressions}
|
||
|
||
Выражение представляет собой функцию, идентификатор, литерал, применение оператора, выражение в скобках, подзапрос, звёздочку. А также может содержать синоним.
|
||
Список выражений - одно выражение или несколько выражений через запятую.
|
||
Функции и операторы, в свою очередь, в качестве аргументов, могут иметь произвольные выражения.
|