查询解析
- 完整的 SQL 解析器 (递归下降解析器) 。
- 数据格式解析器 (快速流式解析器) 。
INSERT 查询之外的所有场景,而 INSERT 查询会同时使用这两种解析器。
让我们来看下面这个查询:
INSERT 查询会同时用到这两种解析器。
INSERT INTO t VALUES 这一片段由完整解析器解析,
而数据 (1, 'Hello, world'), (2, 'abc'), (3, 'def') 则由数据格式解析器 (即快速流式解析器) 解析。
启用完整解析器
启用完整解析器
你也可以通过
input_format_values_interpret_expressions 设置,
为数据启用完整解析器。当上述设置为 1 时,
ClickHouse 会先尝试用快速流式解析器解析这些值。
如果失败,ClickHouse 会再尝试使用完整解析器解析数据,并将其视为 SQL 表达式。INSERT 查询带来的问题,而这也是向 ClickHouse 插入数据的推荐方式。
在 INSERT 查询中使用 Values 格式时,
看起来数据的解析方式似乎与 SELECT 查询中的表达式相同,但实际上并非如此。
Values 格式的能力要受限得多。
本节其余内容将介绍完整解析器。
有关格式解析器的更多信息,请参见 Formats 部分。
空格
- 语法结构之间 (包括查询的开头和结尾) 可以有任意数量的空白字符。
- 空白字符包括空格、制表符、换行符、CR 和换页符。
注释
- SQL 风格注释以
--、#!或#开头,并一直延续到行尾。--和#!后的空格可以省略。 - C 风格注释:
//(或超过 2 个/字符) 后跟文本,并持续到行尾。/后不要求有空格。- 多行注释可以从
/*一直延续到*/。同样不要求有空格。 - C 风格注释可以嵌套。
关键字
- SQL 标准。例如,
SELECT、select和SeLeCt都是有效的。 - 某些流行 DBMS (MySQL 或 Postgres) 中的实现。例如,
DateTime与datetime等同。
你可以在 system.data_type_families 表中查看数据类型名称是否区分大小写。
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。
字面量
String
- 使用前置单引号,此时单引号字符
'(且仅限此字符) 可转义为'';或者 - 使用前置反斜杠,并配合下表中列出的受支持转义序列。
如果反斜杠后面的字符未在下表中列出,则反斜杠会失去其特殊含义,也就是说会按字面值解释。
| Supported Escape | Description |
|---|---|
\xHH | 8 位字符表示法,后跟任意数量的十六进制数字 (H) 。 |
\N | 保留,不执行任何操作 (例如 SELECT 'a\Nb' 返回 ab) |
\a | 响铃 |
\b | 退格 |
\e | 转义字符 |
\f | 换页 |
\n | 换行符 |
\r | 回车 |
\t | 水平制表符 |
\v | 垂直制表符 |
\0 | 空字符 |
\\ | 反斜杠 |
\' (or '') | 单引号 |
\" | 双引号 |
` | 反引号 |
\/ | 正斜杠 |
\= | 等号 |
| ASCII control characters (c <= 31). |
在字符串字面量中,至少需要使用转义码
\' (或 '') 和 \\ 对 ' 和 \ 进行转义。数值
- 如果字面量以前导减号
-开头,则会跳过该标记,并在解析完成后对结果取负。 - 数值字面量首先会使用 strtoull 函数解析为 64 位无符号整数。
- 如果值带有前缀
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]。Tuple 使用 () 构造,例如 (1, 'Hello, world!', 2)。
严格来说,这些并不是字面量,而是分别使用数组创建运算符和 Tuple 创建运算符的表达式。
数组至少必须包含一个元素,而 Tuple 至少必须包含两个元素。
当 Tuple 出现在
SELECT 查询的 IN 子句中时,情况则有所不同。
查询结果可以包含 Tuple,但 Tuple 不能保存到数据库中 (使用 Memory 引擎的表除外) 。NULL
NULL 用于表示值缺失。
要在表字段中存储 NULL,该字段必须为 Nullable 类型。
关于
NULL,请注意以下几点:- 根据数据格式 (输入或输出) 的不同,
NULL可能有不同的表示形式。更多信息,请参见数据格式。 NULL的处理比较微妙。例如,如果比较运算的参数中至少有一个是NULL,则该运算的结果也将是NULL。乘法、加法和其他运算也是如此。建议查阅各个运算对应的文档。- 在查询中,可以使用
IS NULL和IS NOT NULL运算符,以及相关函数isNull和isNotNull来检查NULL。
Heredoc
$ 符号之间。
例如:
- 两个 heredoc 之间的值会按”原样”处理。
定义和使用查询参数
SET param_<name>=<value>— 在查询中使用SET命令。--param_<name>='<value>'— 作为命令行中clickhouse-client的参数。param_<name>=<value>— 作为 HTTP 接口的 URL 查询字符串参数。
{<name>: <datatype>} 引用查询参数,其中 <name> 是查询参数名称,<datatype> 是要转换成的数据类型。
使用 SET 命令的示例
使用 SET 命令的示例
例如,下面的 SQL 定义了名为
a、b、c 和 d 的参数,每个参数的数据类型都不同:使用 clickhouse-client 的示例
使用 clickhouse-client 的示例
如果你使用 如果查询参数表示数据库、表、函数或其他标识符的名称,请使用
clickhouse-client,参数通过 --param_name=value 指定。例如,下面这个参数的名称为 message,并以 String 类型读取:Identifier 作为其类型。例如,下面的查询会返回名为 uk_price_paid 的表中的行:使用 HTTP 接口的示例
使用 HTTP 接口的示例
查询参数可以通过带有
param_ 前缀的 URL 查询字符串参数传递。例如:使用 Web UI 的示例
使用 Web UI 的示例
内置的 Web UI (
play.html) 会自动检测查询中的 {name:Type} 参数占位符,并为每个参数显示带标签的输入框。参数值会包含在 HTTP 请求中,也会保存在页面 URL 中,以便添加书签和共享。查询参数并不是通用的文本替换机制,不能在任意 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 的名称。别名应符合 identifiers 的语法。 | SELECT "table t".column_name FROM table_name AS "table t". |
使用说明
- 别名在查询或子查询中是全局生效的,你可以在查询的任何部分为任何表达式定义别名。例如:
- 别名在子查询内部以及子查询之间都不可见。例如,执行以下查询时,ClickHouse 会抛出异常
Unknown identifier: num:
- 如果在子查询的
SELECT子句中为结果列定义了别名,则这些列在外层查询中也是可见的。例如:
- 请注意避免使用与列名或表名相同的别名。以下是一个示例:
b 的表 t。
然后,在查询数据时,我们定义了别名 sum(b) AS b。
由于别名是全局生效的,
ClickHouse 将表达式 argMax(a, b) 中的字面量 b 替换成了表达式 sum(b)。
这种替换导致了异常。
你可以将 prefer_column_name_to_alias 设置为
1,以更改这一默认行为。星号
SELECT 查询中,星号可用于替代表达式。
更多信息,请参见 SELECT 一节。