您的位置:寻梦网首页编程乐园数据库PostgreSQL 7.2 Documentation

Chapter 1. SQL 语法

本章描述 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 ),那么至少有一个位跟在它后面. 因此,浮点数常量与整数常量的区别是以是否 存在小数点或者指数子句(或者两者都有)为准的.在常量里不能 有空格或者其他字符嵌入在内.

这里是一些合法的浮点数常量的例子:

3.5
4.
.001
5e2
1.925e-3
      

浮点数常量的类型是 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 个字符)个下列字符的序列:

+ - * / < > = ~ ! @ # % ^ & | ` ? $

不过,对操作符名字有几个限制:

  • "$" (美元)不能是单字符操作符,但它可以是一个多字符操作符 名字的一部分.

  • -- /* 不能出现在操作符 名字中的任何地方,因为它们会被当做注释开始对待.

  • 多字符操作符不能以 "+" 或 "-" 结束, 除非其名字至少还包含下列操作符之一:

    ~ ! @ # % ^ & | ` ? $

    比如, @- 是允许的操作符名字, 但 *- 不是.这个限制允许 PostgreSQL 在不要求记号之间有 空白的情况下分析 SQL 兼容的查询.

当你使用非 SQL 标准的操作符名字的时候,你通常需要用 空白分隔相邻的操作符以避免歧义.比如,如果你定义了一个 叫 "@" 的左单目操作符,那么你就不能写 X*@Y ;而是要写成 X* @Y 以确保 PostgreSQL 把它读成两个操作符,而不是一个.

1.1.4. 特殊字符

有些非字母数字字符有一些特殊含义,因此不能用做操作符. 它们的用法的细节可以在相应的描述语法元素的地方找到. 本节只是描述它们的存在和概括一下这些字符的目的.

  • 美元符号( $ )后面跟着数字用于在一个函数体中 表示参数的位置.在其他环境里美元符号可能是一个操作符名字的一部分.

  • 圆括弧( () )用于分组和强制优先级的时候含义 与平常一样.有些场合里圆括弧是作为一个特定 SQL 命令的固定 语法的一部分要求的.

  • 方括弧( [] )用于选取数组元素. 参阅 Chapter 6 获取更多信息.

  • 逗号( , 在一些语法构造里用于分隔 一个列表的元素.

  • 分号( ; )结束一条 SQL 命令. 它不能出现在一条命令里的任何地方,除非引起来当做字符串常量 或者标识符用.

  • 冒号 ( : )用于从数组中选取 "片段" .(参阅 Chapter 6 .)在一些 SQL 方言里(比如嵌入 SQL ), 冒号用于前缀变量名.

  • 星号 ( * 在和 SELECT 命令或 COUNT 聚集函数一起使用时有特殊含义.

  • 句点 ( . 用在浮点数常量里, 并用于分隔表和字段名字.

1.1.5. 注释

注释是任意以双划线开头并延伸到行尾的任意字符序列,比如:

-- This is a standard SQL92 comment

另外,还可以使用 C-风格的块注释:

/* 多行注释
 * 可以嵌套∶/* 嵌套的块注释 */
 */

这里注释以 /* 开头并扩展到对应的 */ .这些块注释可以嵌套,就象 SQL99 里说的那样, 但和 C 不一样,因此我们可以注释掉一大块已经包含块注释的代码.

注释在进一步的语法分析之前被从输入流删除并有效地用空白代替.

Notes

[1]

PostgreSQL 里对未加引号的名子总是 转换成小写, 这和 SQL 是不兼容的,SQL 里要求未引起来的名字总是转成大写. 因此 foo 等于 "FOO" . 如果你想写可移植的程序,那么我们建议你要么就总是引起某个 名字,要么就坚决不引.