描述通用的 SQL 语法。
SQL 输入由一系列命令组成. 一条命令是由一系列记号构成, 用一个分号(“;”)结尾. 输入流的终止也结束一条命令.那些记号是合法的取决于特定命令的语法.
记号可以是一个关键字, 一个标识符,一个 引起的标识符, 一个文本(或常量),或者是特殊的字符符号. 记号通常由空白分隔(空格,tab,换行符),但如果不存在混淆 的时候也可以不用(通常只是一个特殊字符与一些其它记号类型相联 的时候).
另外,在 SQL 输入里可以有注释. 它们不是记号,它们实际上等效于空白.
比如,下列命令是(语法上)合法的 SQL 输入:
SELECT * FROM MY_TABLE; UPDATE MY_TABLE SET A = 5; INSERT INTO MY_TABLE VALUES (3, 'hi there');这里是三条命令的序列,每条一行(尽管并不要求这么做; 多条命令可以在一行里,并且命令可以合理地分裂成多个行).
如果从哪些记号标识命令,哪些是操作数或参数的角度考虑, SQL 语法并不是非常一致.通常头几个记号是命令名字, 因此上面的例子我们通常可以说是一个“SELECT”, 一个“UPDATE”,和一个“INSERT”命令. 不过, UPDATE 命令总是要求一个 SET 在某个位置出现,并且这个变体的 INSERT 还要求有一个 VALUES 才完整.每条命令的准确语法规则都在 参考手册里描写.
象上面的例子里的 SELECT,UPDATE, 或 VALUES 这样的记号都是关键字 的例子,也就是那些在 SQL 语言里有固定含义的单词. 记号 MY_TABLE 和 A 是 标识符的例子.根据使用它们的命令的不同, 它们标识表,字段,或者其它数据库对象的名字. 因此,有时候只是简单地叫它们“名字”. 关键字和标识符有着同样的词法结构,意思是我们在没有认识这种语言 之前是无法区分一个记号是标识符还是名字.你可以在 Appendix B 里找到一个关键字的完整列表.
SQL 标识符和关键字必须以一个字母开头 (a-z) 或下划线开头 (_)开头.标识符和关键字里随后的字符可以是 字母,数字(0-9), 或者下划线,但 SQL 标准不会定义包含数字或者以下划线开头或结尾的 关键字.
PostgreSQL 系统使用不超过 NAMEDATALEN-1 个字符作为标识符; 你可以在命令中写更长的名字,但它们会被截断.缺省时, NAMEDATALEN 是 32,因此标识符最大长度是31 (不过在制作系统的时候,你可以在 src/include/postgres_ext.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;
引起标识符可以包含除引号本身以外的任何其它字符. 这样我们就可以构造那些原本是不允许的表或者字段名字, 比如那些包含空白或与号的名字.但长度限制依旧.
把一个标识符引起来同时也令它大小写相关,而没有引起来的名字 总是转成小写.比如,我们认为标识符 FOO,foo 和 "foo" 是一样的 Postgres名字, 但 "Foo" 和 "FOO" 与上面三个以及它们之间都是不同的. [1]
在 Postgres 里有四种 隐含类型的常量: 字符串,位串,整数,和浮点数. 常量也可以声明为明确的类型,这样就可以使用更准确的表现形式 以及可以通过系统更有效地处理.隐含常量在下面描述; 明确常量稍后描述.
SQL 里的字符串常量是一个由单引号(“'”) 圈定范围的任意字符的序列,比如, 'This is a string'. SQL 允许你在字符串里嵌入单引号,方法是敲入两个连续的单引号 (比如,'Dianne''s horse'). 在 Postgres 里,单引号还可以用 一个反斜扛(“\”)来逃逸,比如, 'Dianne\'s horse'.
还可以使用 C-风格的反斜扛逃逸: \b 是一个退格,\f 是一个进纸,\n 是一个换行符, \r 是一个回车,\t 是一个水平制表符,而\xxx, 这里 xxx 是一个八进制数,是对应 ASCII 码的字符.任何其它跟在反斜扛后面的字符都当做文本看待. 因此,要在字符串常量里包含反斜扛,你可以敲两个反斜扛.
编码为零的字符不能出现在字符串常量中.
两个只是通过至少有一个换行符的空白 分隔的字符串常量会被连接在一起,并当做它们是写成一个常量处理. 比如:
SELECT 'foo' 'bar';等效于
SELECT 'foobar';而
SELECT 'foo' 'bar';是非法的语法.
位串常量看起来很象在开引号前面有一个 B (大写或小写)的字符串(它们之间没有空白), 比如 B'1001'.位串常量里可以用的字符只有 0 和 1.位串常量可以象普通字符串常量那样跨多个行.
SQL 里的整数常量是用不带小数点的十进制数据位(0 到 9) 的序列表示的.合法值的范围取决于所用的整数数据类型, 简单的 integer 类型接受的范围是 从 -2147483648 到 +2147483647.(可选的正号或负号实际上 是一个独立的单目操作符,而不是整数常量的一部分.)
浮点数常量接受下列通用的形式:
digits.[digits][e[+-]digits] [digits].digits[e[+-]digits] digitse[+-]digits这里的 digits 是一个或多个十进制位. 至少有一位在小数点后面或者如果你使用了 e 选项的话在它后面.因此,浮点数常量与整数常量的区别是以是否 存在小数点或者指数子句(或者两者都有)为准的.在常量里不能 有空格或者其他字符嵌入在内.
这里是一些合法的浮点数常量的例子:
3.5
4.
.001
5e2
1.925e-3
浮点数常量的类型是 DOUBLE PRECISION. 你可以用 SQL 字符串表示法或者 Postgres 类型表示法明确声明 REAL:
REAL '1.23' -- string style '1.23'::REAL -- Postgres (historical) style
任意类似的常量可以用下列表示法中的 任何一种来输入:
type 'string' 'string'::type CAST ( 'string' AS type )在字符串里的数值传递给那种叫type 的类型的输入转换过程.结果是这种类型的一个常量. 如果不存在该常量所属类型的歧义,那么明确的类型映射可以省略 (比如,当你把它当做一个没有重载的函数的参数传递时), 这种情况下它会自动转换.
我们还可以用函数样的语法来声明类型转换:
typename ( value )不过这种方法只能用于那些名字同时也是函数名字的类型. (比如,double precision 就不能这么用 -- 但等效的 float8 却可以.)
::,CAST(),和 函数调用语法也可以用于声明任意表达式的类型,但是 type 'string' 的形式只能用于声明一个文本常量的类型.
数组常量的通用格式如下:
'{ val1 delim val2 delim ... }'这里 delim 是该类型的分隔符字符, 和在它的 pg_type 记录里记录的一样. (对于所有内建类型,它是逗号字符 ",".) 每个 val 要么是该数组元素类型的常量, 要么是一个子数组.下面是一个数组常量的例子
'{{1,2,3},{4,5,6},{7,8,9}}'这个常量是两维,3 乘 3数组,组成三个整数的子数组.
独立的数组元素可以放在双引号(" ) 中间以避免 因空白带来的歧义. 如果没有引号,那么数组值分析器就会忽略开头的空白.
(数组常量实际上只是我们前面讨论的通用类型常量的一种特例. 该常量开始是当做字符串对待的然后传递给数组输入转换过程. 可能需要明确地类型声明.)
一个操作符是最多 NAMEDATALEN-1 (缺省 31 个字符)个下列字符的序列:
+ - * / < > = ~ ! @ # % ^ & | ` ? $
不过,对操作符名字有几个限制:"$" (美元)不能是单字符操作符,但它可以是一个多字符操作符 名字的一部分.
-- 和 /* 不能出现在操作符 名字中的任何地方,因为它们会被当做注释开始对待.
多字符操作符不能以 "+" 或 "-" 结束, 除非其名字至少还包含下列操作符之一:
~ ! @ # % ^ & | ` ? $
比如,@- 是允许的操作符名字, 但 *- 不是.这个限制允许 Postgres 在不要求记号之间有 空白的情况下分析 SQL 兼容的查询.当你使用非 SQL 标准的操作符名字的时候,你通常需要用 空白分隔相邻的操作符以避免歧义.比如,如果你定义了一个 叫 "@" 的左单目操作符,那么你就不能写 X*@Y;而是要写成 X* @Y 以确保 Postgres 把它读成两个操作符,而不是一个.
有些非字母数字字符有一些特殊含义,因此不能用做操作符. 它们的用法的细节可以在相应的描述语法元素的地方找到. 本节只是描述它们的存在和概括一下这些字符的目的.
美元符号($)后面跟着数字用于在一个函数体中 表示参数的位置.在其他环境里美元符号可能是一个操作符名字的一部分.
圆括弧(())用于分组和强制优先级的时候含义 与平常一样.有些场合里圆括弧是作为一个特定 SQL 命令的固定 语法的一部分要求的.
方括弧([])用于选取数组元素. 参阅 Chapter 6 获取更多信息.
逗号(,在一些语法构造里用于分隔 一个列表的元素.
分号(;)结束一条 SQL 命令. 它不能出现在一条命令里的任何地方,除非引起来当做字符串常量 或者标识符用.
冒号 (:)用于从数组中选取 “片段”.(参阅 Chapter 6.)在一些 SQL 方言里(比如嵌入 SQL ), 冒号用于前缀变量名.
星号 (*在和 SELECT 命令或 COUNT 聚集函数一起使用时有特殊含义.
句点 (.用在浮点数常量里, 并用于分隔表和字段名字.
注释是任意以双划线开头并延伸到行尾的任意字符序列,比如:
-- This is a standard SQL92 comment
另外,还可以使用 C-风格的块注释:
/* multi-line comment * with nesting: /* nested block comment */ */这里注释以 /* 开头并扩展到对应的 */.这些块注释可以嵌套,就象 SQL99 里说的那样, 但和 C 不一样,因此我们可以注释掉一大块已经包含块注释的代码.
注释在进一步的语法分析之前被从输入流删除并有效地用空白代替.
[1] | Postgres 对未加引号的名子总是 转换成小写, 这和 SQL 是不兼容的,SQL 里未引起来的名字总是转成大写. 因此 foo 等于 "FOO". 如果你想写可移植的程序,那么我们建议你要么就总是引起某个 名字,要么就坚决不引. |