词法结构
Elastic Stack Serverless
本节介绍 SQL 的主要词法结构,在很大程度上,它类似于 ANSI SQL 本身,因此不深入讨论底层细节。
Elasticsearch SQL 目前一次只接受一个命令。 命令是由输入流结束符终止的token序列。
token 可以是关键字、标识符(带引号或不带引号)、字面量(或常量)或特殊字符符号(通常是分隔符)。 token 通常由空格(空格、制表符)分隔,但在某些情况下,如果没有歧义(通常是由于字符符号),则不需要空格 - 但为了便于阅读,应避免这样做。
以下面的示例为例
SELECT * FROM table
该查询有四个 token:SELECT
、*
、FROM
和 table
。 前三个,即 SELECT
、*
和 FROM
是关键字,表示在 SQL 中具有固定含义的词。 token table
是一个标识符,表示它在 SQL 内部标识(通过名称)一个实体,例如表(在本例中)、列等……
可以看出,关键字和标识符具有相同的词法结构,因此如果不了解 SQL 语言,就无法知道一个 token 是哪一个; 关键字的完整列表可在保留附录中找到。 请注意,关键字不区分大小写,这意味着之前的示例可以写成
select * fRoM table;
但是标识符却不是这样 - 由于 Elasticsearch 区分大小写,Elasticsearch SQL 会逐字使用接收到的值。
为了帮助区分两者,在整个文档中,SQL 关键字都采用大写形式,我们发现这种约定提高了可读性,因此推荐给其他人。
标识符可以有两种类型:带引号和不带引号
SELECT ip_address FROM "hosts-*"
此查询有两个标识符,ip_address
和 hosts-*
(一个 索引模式)。 由于 ip_address
与任何关键字都不冲突,因此可以逐字使用,另一方面,hosts-*
不能使用,因为它与 -
(减号运算)和 *
冲突,因此需要使用双引号。
另一个例子
SELECT "from" FROM "<logstash-{now/d}>"
第一个标识符 from 需要用引号引起来,否则它会与 FROM
关键字冲突(关键字不区分大小写,因此可以写成 from
),而第二个标识符使用 Elasticsearch 索引和索引别名名称中的日期数学支持 否则会混淆解析器。
因此,通常,尤其是在处理用户输入时,强烈建议对标识符使用引号。 它只会稍微增加查询的复杂性,但作为回报,它可以提供清晰性和消除歧义。
Elasticsearch SQL 支持两种隐式类型字面量:字符串和数字。
字符串字面量是由单引号 '
界定的任意数量的字符:'Giant Robot'
。 要在字符串中包含单引号,请使用另一个单引号对其进行转义:'Captain EO''s Voyage'
。
转义的单引号不是双引号 ("
),而是重复的单引号 '
(''
)。
数字字面量以十进制和科学计数法形式接受,带有指数标记(e
或 E
),以数字或小数点 .
开头。
1969 -- integer notation
3.14 -- decimal notation
.1234 -- decimal notation starting with decimal point
4E5 -- scientific notation (with exponent marker)
1.2e-3 -- scientific notation with decimal point
包含小数点的数字字面量始终被解释为 double
类型。 那些不包含小数点的,如果适合则被认为是 integer
,否则它们的类型是 long
(或 ANSI SQL 类型中的 BIGINT
)。
在处理任意类型字面量时,可以通过强制转换来创建对象,通常是将字符串表示形式转换为所需的类型。 这可以通过专用的 cast 运算符 和 函数来实现。
123::LONG -- cast 123 to a LONG
CAST('1969-05-13T12:34:56' AS TIMESTAMP) -- cast the given string to datetime
CONVERT('10.0.0.1', IP) -- cast '10.0.0.1' to an IP
请注意,Elasticsearch SQL 提供了开箱即用的返回常用字面量(如 E()
)或为某些字符串提供专用解析的函数。
值得指出的是,在 SQL 中,单引号 '
和双引号 "
具有不同的含义,并且不能互换使用。 单引号用于声明字符串字面量,而双引号用于标识符。
证明如下
SELECT "first_name"
FROM "musicians"
WHERE "last_name"
= 'Carroll'
- 双引号
"
用于列和表标识符 - 单引号
'
用于字符串字面量
要转义单引号或双引号,需要再次使用该特定引号。 例如,字面量 John's
可以像这样转义 SELECT 'John''s' AS name
。 双引号转义也是如此 - SELECT 123 AS "test""number"
将显示一个名为 test"number
的列。
一些非字母数字字符具有与运算符不同的专用含义。 为了完整起见,这些字符在下面指定
字符 | 描述 |
---|---|
* |
星号(或通配符)在某些上下文中用于表示表的所有字段。 也可以用作某些聚合函数的参数。 |
, |
逗号用于枚举列表的元素。 |
. |
用于数字常量或分隔标识符限定符(目录、表、列名等……)。 |
() |
括号用于特定的 SQL 命令、函数声明或强制优先级。 |
Elasticsearch SQL 中的大多数运算符具有相同的优先级并且是左结合的。 由于这是在解析时完成的,因此需要使用括号来强制不同的优先级。
下表指示了支持的运算符及其优先级(从高到低);
运算符/元素 | 结合性 | 描述 |
---|---|---|
. |
左 | 限定符分隔符 |
:: |
左 | PostgreSQL 风格的类型转换 |
+ - |
右 | 一元加号和减号(数字字面量符号) |
* / % |
左 | 乘法、除法、取模 |
+ - |
左 | 加法、减法 |
BETWEEN IN LIKE |
范围包含、字符串匹配 | |
< > <= >= = <=> <> != |
比较 | |
NOT |
右 | 逻辑否定 |
AND |
左 | 逻辑与 |
OR |
左 | 逻辑或 |
Elasticsearch SQL 允许注释,注释是解析器忽略的字符序列。
支持两种样式
- 单行
- 注释以双破折号
--
开头,并持续到行尾。 - 多行
- 以
/*
开头并以*/
结尾的注释(也称为 C 样式)。
-- single line comment
/* multi
line
comment
that supports /* nested comments */
*/