4.1. 词法结构
SQL输入由一个命令序列组成。一个命令由一个记号的序列构成,并由一个分号(“;”)终结。输入流的末端也会标志一个命令的结束。具体哪些记号是合法的与具体命令的语法有关。
一个记号可以是一个关键词、一个标识符、一个带引号的标识符、一个literal(或常量)或者一个特殊字符符号。记号通常以空白(空格、制表符、新行)来分隔,但在无歧义时并不强制要求如此(唯一的例子是一个特殊字符紧挨着其他记号)。
例如,下面是一个(语法上)合法的SQL输入:
SELECT * FROM MY_TABLE; UPDATE MY_TABLE SET A = 5; INSERT INTO MY_TABLE VALUES (3, 'hi there');
这是一个由三个命令组成的序列,每一行一个命令(尽管这不是必须地,在同一行中可以有超过一个命令,而且命令还可以被跨行分割)。
另外,注释也可以出现在SQL输入中。它们不是记号,它们和空白完全一样。
根据标识命令、操作符、参数的记号不同,SQL的语法不很一致。最前面的一些记号通常是命令名,因此在上面的例子中我们通常会说一个“SELECT”、一个“UPDATE”和一个“INSERT”命令。但是例如UPDATE
命令总是要求一个SET
记号出现在一个特定位置,而INSERT
则要求一个VALUES
来完成命令。每个命令的精确语法规则在第 VI 部分中介绍。
4.1.1. 标识符和关键词
上例中的SELECT
、UPDATE
或VALUES
记号是关键词的例子,即SQL语言中具有特定意义的词。记号MY_TABLE
和A
则是标识符的例子。它们标识表、列或者其他数据库对象的名字,取决于使用它们的命令。因此它们有时也被简称为“名字”。关键词和标识符具有相同的词法结构,这意味着我们无法在没有语言知识的前提下区分一个标识符和关键词。一个关键词的完整列表可以在附录 C中找到。
SQL标识符和关键词必须以一个字母(a
-z
,也可以是带变音符的字母和非拉丁字母)或一个下划线(_)开始。后续字符可以是字母、下划线(_
)、数字(0
-9
)或美元符号($
)。注意根据SQL标准的字母规定,美元符号是不允许出现在标识符中的,因此它们的使用可能会降低应用的可移植性。SQL标准不会定义包含数字或者以下划线开头或结尾的关键词,因此这种形式的标识符不会与未来可能的标准扩展冲突 。
系统中一个标识符的长度不能超过 NAMEDATALEN
-1 字节,在命令中可以写超过此长度的标识符,但是它们会被截断。默认情况下,NAMEDATALEN
的值为64,因此标识符的长度上限为63字节。如果这个限制有问题,可以在src/include/pg_config_manual.h
中修改 NAMEDATALEN
常量。
UPDATE MY_TABLE SET A = 5;
可以等价地写成:
uPDaTE my_TabLE SeT a = 5;
一个常见的习惯是将关键词写成大写,而名称写成小写,例如:
UPDATE my_table SET a = 5;
这里还有第二种形式的标识符:受限标识符或被引号修饰的标识符。它是由双引号("
)包围的一个任意字符序列。一个受限标识符总是一个标识符而不会是一个关键字。因此"select"
可以用于引用一个名为“select”的列或者表,而一个没有引号修饰的select
则会被当作一个关键词,从而在本应使用表或列名的地方引起解析错误。在上例中使用受限标识符的例子如下:
UPDATE "my_table" SET "a" = 5;
受限标识符可以包含任何字符,除了代码为0的字符(如果要包含一个双引号,则写两个双引号)。这使得可以构建原本不被允许的表或列的名称,例如包含空格或花号的名字。但是长度限制依然有效。
一种受限标识符的变体允许包括转义的用代码点标识的Unicode字符。这种变体以U&
(大写或小写U跟上一个花号)开始,后面紧跟双引号修饰的名称,两者之间没有任何空白,如U&"foo"
(注意这里与操作符&
似乎有一些混淆,但是在&
操作符周围使用空白避免了这个问题) 。在引号内,Unicode字符可以以转义的形式指定:反斜线接上4位16进制代码点号码或者反斜线和加号接上6位16进制代码点号码。例如,标识符"data"
可以写成:
U&"d\0061t\+000061"