|
Chapter 1. SQL 语法1.1. 词法结构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 才完整.每条命令的准确语法规则都在 参考手册 里描写. 1.1.1. 标识符和关键字象上面的例子里的 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" 是一样的 PostgreSQL 名字, 但 "Foo" 和 "FOO" 与上面三个以及它们之间都是不同的. [1] 1.1.2. 常量在 PostgreSQL 里有四种 隐含类型的常量 : 字符串,位串,整数,和浮点数. 常量也可以声明为明确的类型,这样就可以使用更准确的表现形式 以及可以通过系统更有效地处理.隐含常量在下面描述; 明确常量稍后描述. 1.1.2.1. 字符串常量SQL 里的字符串常量是一个由单引号( "'" ) 圈定范围的任意字符的序列,比如, 'This is a string' . SQL 允许你在字符串里嵌入单引号,方法是敲入两个连续的单引号 (比如, 'Dianne''s horse' ). 在 PostgreSQL 里,单引号还可以用 一个反斜扛( "\" )来逃逸,比如, 'Dianne\'s horse' . 还可以使用 C-风格的反斜扛逃逸: \b 是一个退格, \f 是一个进纸, \n 是一个换行符, \r 是一个回车, \t 是一个水平制表符,而 \ xxx , 这里 xxx 是一个八进制数,是对应 ASCII 码的字符.任何其它跟在反斜扛后面的字符都当做文本看待. 因此,要在字符串常量里包含反斜扛,你可以敲两个反斜扛. 编码为零的字符不能出现在字符串常量中. 两个只是通过 至少有一个换行符 的空白 分隔的字符串常量会被连接在一起,并当做它们是写成一个常量处理. 比如: SELECT 'foo' 'bar'; 等效于 SELECT 'foobar'; 而 SELECT 'foo' 'bar'; 是非法的语法,而在这方面 PostgreSQL 与 SQL9x 一致. 1.1.2.2. 位串常量位串常量看起来很象在开引号前面有一个 B (大写或小写)的字符串(它们之间没有空白), 比如 B'1001' .位串常量里可以用的字符只有 0 和 1 .位串常量可以象普通字符串常量那样跨多个行. 1.1.2.3. 整数常量SQL 里的整数常量是用不带小数点的十进制数据位(0 到 9), 也没有指数位, 的序列表示的.合法值的范围取决于所用的整数数据类型, 简单的 integer 类型接受的范围是 从 -2147483648 到 +2147483647.(可选的正号或负号实际上 是一个独立的单目操作符,而不是整数常量的一部分.) 1.1.2.4. 浮点数常量浮点数常量接受下列通用的形式: digits .[ digits ][ e[ +- ] digits ] [ digits ]. digits [ e[ +- ] digits ] digits e[ +- ] digits 这里的 digits 是一个或多个十进制位. 至少有一位在小数点前面或后面.如果出现了指数分隔符 ( e ),那么至少有一个位跟在它后面. 因此,浮点数常量与整数常量的区别是以是否 存在小数点或者指数子句(或者两者都有)为准的.在常量里不能 有空格或者其他字符嵌入在内. 浮点数常量的类型是 DOUBLE PRECISION . 你可以用 SQL 字符串表示法或者 PostgreSQL 类型表示法明确声明 REAL : REAL '1.23' -- string style '1.23'::REAL -- PostgreSQL (historical) style
1.1.2.5. 其它类型的常量任意 类似的常量可以用下列表示法中的 任何一种来输入: type ' string ' ' string ':: type CAST ( ' string ' AS type ) 在字符串的文本将传递给那种叫 type 的类型的输入转换过程.结果是这种类型的一个常量. 如果不存在该常量所属类型的歧义,那么明确的类型映射可以省略 (比如,当你把它当做一个没有重载的函数的参数传递时), 这种情况下它会自动转换. 我们还可以用函数样的语法来声明类型转换: typename ( ' string ' ) 不过并非所有类型名可以这样使用;参阅 Section 1.3.6 获取细节. :: , CAST() ,和 函数调用语法也可以用于声明任意表达式的运行时类型转换, 如 Section 1.3.6 中讨论的那样. 但是 type ' string ' 的形式只能用于声明一个文本常量的类型. type ' string ' 的另外一个限制是它不能用于数组类型;要用 :: 或者 CAST() 声明一个数组常量的类型. 1.1.2.6. 数组常量数组常量的通用格式如下: '{ val1 delim val2 delim ... }' 这里 delim 是该类型的分隔符字符, 和在它的 pg_type 记录里记录的一样. (对于所有内建类型,它是逗号字符 ",".) 每个 val 要么是该数组元素类型的常量, 要么是一个子数组.下面是一个数组常量的例子 '{{1,2,3},{4,5,6},{7,8,9}}' 这个常量是两维,3 乘 3数组,组成三个整数的子数组. 独立的数组元素可以放在双引号( " ) 中间以避免 因空白带来的歧义. 如果没有引号,那么数组值分析器就会忽略开头的空白. (数组常量实际上只是我们前面讨论的通用类型常量的一种特例. 该常量开始是当做字符串对待的然后传递给数组输入转换过程. 可能需要明确地类型声明.) 1.1.3. 操作符一个操作符是最多 NAMEDATALEN -1 (缺省 31 个字符)个下列字符的序列: + - * / < > = ~ ! @ # % ^ & | ` ? $ 不过,对操作符名字有几个限制:
当你使用非 SQL 标准的操作符名字的时候,你通常需要用 空白分隔相邻的操作符以避免歧义.比如,如果你定义了一个 叫 "@" 的左单目操作符,那么你就不能写 X*@Y ;而是要写成 X* @Y 以确保 PostgreSQL 把它读成两个操作符,而不是一个. 1.1.4. 特殊字符有些非字母数字字符有一些特殊含义,因此不能用做操作符. 它们的用法的细节可以在相应的描述语法元素的地方找到. 本节只是描述它们的存在和概括一下这些字符的目的.
1.1.5. 注释注释是任意以双划线开头并延伸到行尾的任意字符序列,比如: -- This is a standard SQL92 comment
另外,还可以使用 C-风格的块注释: /* 多行注释 * 可以嵌套∶/* 嵌套的块注释 */ */ 这里注释以 /* 开头并扩展到对应的 */ .这些块注释可以嵌套,就象 SQL99 里说的那样, 但和 C 不一样,因此我们可以注释掉一大块已经包含块注释的代码. 注释在进一步的语法分析之前被从输入流删除并有效地用空白代替. Notes
|