PostgreSQL语法结构

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 才完整。每条命令的准确语法规则都在 Part VI 里描述。

4.1.1. 标识符和关键字

像上面例子里的 SELECT, UPDATE, VALUES 这样的记号都是关键字的例子,也就是那些在 SQL 语言里有固定含义的单词。记号 MY_TABLEA标识符的例子。根据使用它们的命令的不同,它们标识表、字段、或者其它数据库对象的名字。因此,有时候只是简单地叫它们"名字"。关键字和标识符有着同样的词法结构,意思是我们在没有认识这种语言之前是无法区分一个记号是标识符还是名字。你可以在附录C里找到一个关键字的完整列表。

SQL 标识符和关键字必须以一个字母(a-z 以及带变音符的字母和非拉丁字母)或下划线(_)开头,随后的字符可以是字母、下划线、数字(0-9)、美元符号($)。需要注意的是,根据 SQL 标准,美元符号不允许出现在标识符中,因此使用美元符号将不易移植。SQL 标准不会定义包含数字或者以下划线开头或结尾的关键字,因此按照这里的格式定义的标识符是安全的,不会和将来标准的扩展特性冲突。

系统使用不超过 NAMEDATALEN-1 个字符作为标识符;你可以在命令中写更长的名字,但它们会被截断。NAMEDATALEN 的缺省值是 64 ,因此标识符最大长度是 63 。如果觉得这个限制有问题,那么你可以在 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 将被当做一条命令的一部分,因此如果把它当做一个表名或者字段名使用的话就会产生一个分析错误。上面的例子可以用引号包围的标识符这么写:

UPDATE "my_table" SET "a" = 5;

引号包围的标识符可以包含编码不等于零的任意字符(要包含一个双引号,可以写两个相连的双引号)。这样我们就可以构造那些原本是不允许的表名或者字段名,比如那些包含空白或与号(&)的名字。但长度限制依旧。

把一个标识符用引号包围起来同时也令它大小写相关,而没有引号包围起来的名字总是转成小写。比如,我们认为标识符 FOO, foo, "foo" 是等价的 PostgreSQL 名字,但 "Foo""FOO" 与上面三个以及它们之间都是不同的。PostgreSQL 里对未加引号的名子总是转换成小写,这和 SQL 标准是不兼容的,SQL 标准要求未用引号包围起来的名字总是转成大写。因此根据标准,foo 等于 "FOO" 但不等于 "foo" 。如果你想编写可移植的程序,那么我们建议你要么就总是用引号包围某个名字,要么就从来不引。

4.1.2. 常量

在 PostgreSQL 里有三种隐含类型的常量:字符串、位串、数值。常量也可以声明为明确的类型,这样就可以使用更准确的表现形式以及可以通过系统更有效地处理。这些将在后面的小节描述。

4.1.2.1. 字符串常量

SQL 里的一个字符串文本是用单引号()包围的任意字符序列,比如 ‘This is a string‘ 。这种声明字符串常量的方法是 SQL 标准定义的。在这种类型的字符串常量里嵌入单引号的标准兼容的做法是敲入两个连续的单引号,比如 ‘Dianne‘‘s horse‘ 。注意:两个连续的单引号不是双引号(")。

两个只是通过至少一个换行符的空白分隔的字符串常量会被连接在一起,并当做它们是写成一个常量处理。比如:

SELECT ‘http://www.infocool.net‘
‘bar‘;

等效于

SELECT ‘http://www.infocool.netbar‘;

SELECT ‘http://www.infocool.net‘      ‘bar‘;

是非法的语法。这个怪异的行为是 SQL 声明的,PostgreSQL 遵循标准。

PostgreSQL 还允许 "逃逸"字符串中的内容,这是一个 PostgreSQL 对 SQL 标准的扩展。逃逸字符串语法是通过在字符串前写字母 E(大写或者小写)的方法声明的。比如 E‘foo‘ 。当需要续行包含逃逸字符的字符串时,仅需要在第一行的开始引号前写上 E 就可以了。逃逸字符串使用的是C-风格的反斜杠(\)逃逸:\b(退格)、\f(进纸)、\n(换行)、\r(回车)、\t(水平制表符)。此外还支持 \digits 格式的逃逸字符(这里的 digits 是一个八进制字节数值),以及 \xhexdigits 格式的逃逸字符(这里的hexdigits 代表十六进制字节值)。你创建的字节序列是否是服务器的字符集编码能接受的正确字符,是你自己的责任。任何其它跟在反斜杠后面的字符都当做文本看待。因此,要在字符串常量里包含反斜杠,则写两个反斜杠(\\)。另外,PostgreSQL 允许用一个反斜杠来逃逸单引号(\‘),不过,将来版本的 PostgreSQL 将不允许这么用。所以最好坚持使用符合标准的 ‘‘

警告

如果配置参数 standard_conforming_strings 的值是 off ,那么 PostgreSQL 将能够识别所有(无论有无前导 E)字符串常量中的反斜杠逃逸,这是为了与过去的历史行为兼容。虽然 standard_conforming_strings 目前的默认值是 off ,但是在不久的将来会变成 on 以与标准兼容。我们鼓励在应用中不使用反斜杠逃逸。如果你确实需要使用反斜杠逃逸来表示特殊字符,那么请在字符串常量前加上 E 以确保能够被正确的处理。

standard_conforming_strings 之外,escape_string_warningbackslash_quote 配置参数也影响字符串常量中反斜杠的处理。

编码为零的字符不允许出现在字符串常量中。

4.1.2.2. 美元符界定字符串常量

尽管声明字符串常量的标准方法通常都很方便,但是如果字符串中包含很多单引号或者反斜杠,那么理解字符串的内容可能就会变得很苦涩,因为每个单引号都要加倍。为了让这种场合下的查询更具可读性,PostgreSQL 允许另外一种称作"美元符界定"的字符串常量书写办法。一个通过美元符界定声明的字符串常量由一个美元符号($)、零个或多个字符组成的"记号"、另一个美元符号、组成字符串常量的任意字符序列、一个美元符号、与前面相同的记号、一个美元符号组成的。比如,下面是两个不同的用美元符界定的方法声明"Dianne‘s horse"的例子:

$$Dianne‘s horse$$
$SomeTag$Dianne‘s horse$SomeTag$

请注意,在美元符界定的字符串里,单引号不允许逃逸。实际上,在一个美元符界定的字符串里,不允许逃逸任何字符:字符串内容总是按照字面内容书写。反斜杠不是特殊的、美元符自己也不是特殊的(除非它们和开标签的一部分匹配)。

我们可以通过在不同嵌套级别使用不同的"标记"来实现嵌套。最常见的是写函数定义的时候。比如:

$function$
BEGIN
    RETURN ($1 ~ $q$[\t\r\n\v\\]$q$);
END;
$function$

这里,序列 $q$[\t\r\n\v\\]$q$ 表示一个美元符界定的字符串文本 [\t\r\n\v\\] ,在函数体被 PostgreSQL 执行的时候,它将被识别出来。但是因为这个序列不匹配外层的界定符 $function$ ,所以只要考虑了外层字符串,它就只是常量里面的普通字符而已。

如果有标签的话,一个美元符界定的字符串遵循和无引号包围的标识符相同的规则,只是它不能包含美元符。标签是大小写相关的,因此 $tag$String content$tag$ 是正确的,而 $TAG$String content$tag$ 则是错误的。

一个后面紧跟着关键字或者标识符的美元符界定字符串必须用空白与其后的关键字或者标识符隔开;否则美元符界定符将会被当作标识符的开头部分([原文] otherwise the dollar quoting delimiter would be taken as part of the preceding identifier)。

美元符界定不是 SQL 标准,但是在写复杂的字符串文本的时候,它通常比标准的单引号语法更方便。尤其是在其它常量里表现字符串常量的时候更有用。比如在过程函数定义里,如果用单引号语法,每个上面例子里的每个反斜杠都必须写四个,它们在作为字符串文本分析的时候会减少为两个,然后在函数执行的时候在内层字符串常量里会再次被解析为一个。

4.1.2.3. 位串常量

位串常量看起来很像在开引号前面有一个 B(大写或小写)的普通字符串(它们之间没有空白),比如 B‘1001‘ 。位串常量里可以用的字符只有 01

另外,位串常量可以用十六进制表示法声明,方法是使用前缀 X(大写或者小写),比如 X‘1FF‘ ,其中的每个十六进制位等效于四个二进制位。

两种形式的位串常量都可以像普通字符串常量那样跨行连续。位串常量不能用美元符界定。

4.1.2.4. 数值常量

数值常量接受下列通用的形式:

digits
digits.[digits][e[+-]digits]
[digits].digits[e[+-]digits]
digitse[+-]digits

这里的 digits 是一个或多个十进制数字(0-9)。如果有小数点,那么至少有一位在小数点前面或后面。如果出现了指数分隔符(e)那么至少有一个数字跟在它后面。在常量里不能有空格或者其它字符。请注意任何前导正号或负号实际上都不认为是常量的一部分;它是施加于常量的一个操作符。

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

42
3.5
4.
.001
5e2
1.925e-3

如果一个数值常量既不包含小数点,也不包含指数操作符,那么如果它的数值可以放在 integer 类型中(32位),则认为它是 integer 类型;如果它的数值可以放在
bigint 中(64位),则认为它是 bigint ,否则认为它是 numeric 类型。包含小数点和/或指数操作符的常量总是被认为是 numeric
类型。

给一个数值常量赋予初始数据类型只是类型解析算法的开端。在大多数情况下该常量会根据环境被自动强制转换成最合适的类型。必要时,你可以通过强制类型转换把一个数值解析成特定的数据类型。比如,你可以强制要求把一个数值当作
real(float4) 类型来看,方法是这么写:

REAL ‘1.23‘  -- 字符串风格
1.23::REAL   -- PostgreSQL(历史的)风格 

这些实际上只是下面讨论的通用转换的特例。

4.1.2.5. 其它类型的常量

任意类型的常量都可以用下列表示法中的任何一种来输入:

typestring‘
‘string‘::type
CAST ( ‘string‘ AS type )

其中的 ‘string‘ 将会被转换为 type 类型的常量。如果不存在该常量所属类型的歧义,那么可以省略明确的类型转换(比如,当你把它直接赋予一个表字段的时候),这种情况下它会自动转换。

其中的 ‘string‘ 可以用普通 SQL 表示法或者美元符界定来书写。

我们还可以用函数风格的语法来声明类型转换:

typename ( ‘string‘ )

不过并非所有类型名都可以这样使用;参阅节4.2.8获取细节。

::, CAST() 和函数调用语法也可以用于声明任意表达式的运行时类型转换(如节4.2.8中讨论的那样)。但是 typestring 的形式只能用于声明一个字面常量的类型。typestring 的另外一个限制是它不能用于数组类型(要用 ::CAST() 声明一个数组常量的类型)。

CAST() 语法遵循 SQL 标准。typestring 语法是标准的一个推广:SQL 只是给少数几种数据类型声明了这个语法,但 PostgreSQL允许将其用于所有类型。:: 和函数调用的语法是 PostgreSQL 的历史用法。

4.1.3. 操作符

一个操作符是最多 NAMEDATALEN-1 个(缺省63个)下列字符的序列:

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

不过,有几个限制:

  • --/* 不能出现在操作符中的任何地方,因为它们会被当做注释开始对待。
  • 多字符操作符不能以 +- 结束,除非其中至少还包含下列操作符之一:

    ~ ! @ # % ^ & | ` ?

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

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

4.1.4. 特殊字符

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

  • 美元符号($)后面跟着数字用于在一个函数体定义或者预备语句中表示参数的位置。在其它环境里美元符号可能是一个标识符名字或者是一个美元符界定的字符串常量的一部分。
  • 圆括弧(())用于分组和强制优先级的时候含义与平常一样。有些场合里圆括弧是作为一个特定 SQL 命令的固定语法的一部分要求的。
  • 方括弧([])用于选取数组元素。参阅节8.10获取更多信息。
  • 逗号(,)在一些语法构造里用于分隔一个列表的元素。
  • 分号(;)结束一条 SQL 命令。它不能出现在一条命令里的任何地方,除了在引号包围的字符串常量或者标识符中。
  • 冒号(:)用于从数组中选取"片段"(参阅节8.10)。在一些 SQL 方言里(比如嵌入 SQL),冒号用于前缀变量名。
  • 星号(*)在某些环境里表示一个表的全部字段或者一个复合类型的值。在用作聚集函数的参数时还表示该聚集并不需要明确的参数。
  • 句点(.)用在数字常量里,并用于分隔模式、表、字段名。

4.1.5. 注释

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

-- 这是标准的 SQL92 注释 

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

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

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

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

4.1.6. 词法优先级

表4-1显示了 PostgreSQL 里面的操作符的优先级和关联性。大多数操作符都有相同的优先级并且都是左关联的。这种情况可能会有不那么直观的行为;比如,布尔操作符 <> 与布尔操作符 <=>= 之间有着不同的优先级。同样,当你把双目和单目操作符组合使用的时候,有时候也需要加圆括弧。比如

SELECT 5 ! - 6;

会被分析成

SELECT 5 ! (- 6);

因为分析器不知道 ! 被定义成了后缀操作符,而不是中缀操作符(知道的时候只能是太晚了)。要在本例中获得你需要的特性,你要写成

SELECT (5 !) - 6;

这是我们为扩展性付出的代价。

表4-1. 操作符优先级(递减)

操作符/元素 关联性 描述
. 表/字段名分隔符
:: PostgreSQL 特有的类型转换操作符
[ ] 数组元素选择
- 单目负号
^
* / % 乘,除,模
+ - 加,减
IS   IS TRUE, IS FALSE, IS UNKNOWN, IS NULL
ISNULL   测试是否为 NULL
NOTNULL   测试是否不为 NULL
(任何其它的) 所有其它的本地和用户定义操作符
IN   集合成员
BETWEEN   范围包含
OVERLAPS   时间间隔重叠
LIKE ILIKE SIMILAR   字符串模式匹配
< >   小于,大于
= 等于,赋值
NOT 逻辑非
AND 逻辑与
OR 逻辑或

请注意操作符优先级也适用于和上面提到的同名的内置操作符和用户定义操作符。比如,如果你为一些客户数据类型定义一个"+"操作符,那么它和内置的"+"操作符有同样的优先级,不管用它来干什么。

如果在 OPERATOR 语法里使用了模式修饰的操作符名,比如

SELECT 3 OPERATOR(pg_catalog.+) 4;

那么 OPERATOR 构造就会有表4-1里面为"任何其它"操作符显示的缺省优先级。不管什么特定的操作符出现在 OPERATOR() 里都是这样。

更多信息参考http://www.infocool.net

时间: 2024-10-25 07:44:48

PostgreSQL语法结构的相关文章

foreach ()语法结构提供了遍历数组的简单方式

foreach 语法结构提供了遍历数组的简单方式.foreach 仅能够应用于数组和对象,如果尝试应用于其他数据类型的变量,或者未初始化的变量将发出错误信息.有两种语法: foreach (array_expression as $value) statement foreach (array_expression as $key => $value) statement 第一种格式遍历给定的 array_expression 数组.每次循环中,当前单元的值被赋给 $value 并且数组内部的指

SQL SERVER 2012 第四章 连接 JOIN语句的早期语法结构 &amp; 联合UNION

1/内部连接的早期语法结构 INNER JOIN SELECT * FROM Person.Person JOIN HumanResources.Employee ON Person.Person.ID = HumanResources.Employee.ID 等价于早期的也就是老版本的 SELECT * FROM Person.Person,HumanResources.Employee WHERE Person.Person.ID = HumanResources.Employee.ID 2

PHP 数组遍历 foreach 语法结构

foreach 语法结构用于遍历数组. foreach() PHP foreach() 语法结构用于遍历操作或输出数组,foreach() 仅能用于遍历数组或对象,当试图将其用于其它数据类型或者一个未初始化的变量时会产生错误. 语法: foreach (array as $value) statement // 或者: foreach (array as $key => $value) statement 上述语法中,每次循环将当前单元的值赋给 $value 并且数组内部的指针向前移一步.在第二

Bash编程语法结构第二节

Bash编程语法结构 一.for结构 其中 $var 是循环控制变量,[list] 是 $var 需要遍历的一个集合, do/done 对包含了循环体,相当于 C 语言中的一对大括号.另外如果 do 和 for 被写在同一行,必须在 do 前面加上 ";".如: for $var in [list]; do .下面是一个运用 for 进行循环的例子: 二.while适用于循环次数未知,或不便用for直接生成较大的列表时: while 测试条件; do 循环体 done 测试条件为真,进

多媒体开发之---h264 NALU 语法结构

补充笔记: 关于VCL:VCL层是指视频编码层,VCL NAL 单元是指那些nal_unit_type 值等于 1 到 5(包括 1 和 5)的 NAL 单元,这些单元都包含了视频数据.所有其他的 NAL 单元都称作非 VCL NAL 单元,PPS和SPS都是非VCLNAL单元.关于字节流NAL单元的格式:(起始码中0的长度)除了流开头的字节流NAL单元,大多字节流NAL单元的开头没有leading_zero_8bits (一个字节的0); nal_unit_type等于7(SPS)或8(PPS

黑马程序员——Java基础语法(二)语法结构

-----------android培训.java培训.java学习型技术博客.期待与您交流!------------ Java 中的语法结构有四种 顺序结构:顾名思义,就是按照顺序执行语句 判断结构:if  switch 选择结构: 循环结构:for  while   do while 1. if 结构 if语句有三种结构. (1)if(条件表达式){执行语句;} (2)if(条件表达式){执行语句;} else{执行语句;} (3)if(条件表达式){执行语句;} else if(条件表达式

前端-CSS-初探-注释-语法结构-引入方式-选择器-选择器优先级-01(待完善)

目录 CSS(Cascading Style Sheet) CSS注释 CSS语法结构 CSS的三种引入方式 选择器 伪类.伪元素选择器速查 CSS选择器优先级***** 选择器相同的情况下 选择器不同的情况下 选择器权重 样式调整技巧 本篇博客绝大多数内容来源网上,感谢作者的无私分享~ CSS(Cascading Style Sheet) 用来调节标签样式的,又称层叠样式表 CSS注释 /* 单行注释 */ /* 多行注释 */ 经典写法 /* 这是购物车页面的样式表(一般放css文件的第一行

ajax语法结构

ajax语法结构 特点: ajax(******) 异步提交 同步异步:描述的任务的提交方式 同步:提交任务之后 原地等待任务的返回结果 期间不干任何事儿 异步:提交任务之后 不愿地等待 直接执行下一行代码 任务的返回通过回调机制 阻塞非阻塞:程序的运行状态 程序运行的三状态图 局部刷新 一个页面 不是整体刷新 而是页面的某个地方局部刷新 Ajax是一门js的技术 基于原生js开发的,但是用原生的js写代码过于繁琐 我们在学的时候 只学如何用jQuery实现ajax AJAX 最大的优点是在不重

Oracle 中的基础的一些语法结构

方括号里的内容为可选项 大括号是必填 1PL/SQL结构块 DECLARE /* * 声明部分——定义常量.变量.复杂数据类型.游标.用户自定义异常 */ BEGIN /* * 执行部分——PL/SQL语句和SQL语句 */ EXCEPTION /* * 异常处理部分——处理运行异常 */ END; /*块结束标记 */ 2 创建序列 1 CREATE SEQUENCE [ schema. ] sequence_name 2 [ { INCREMENT BY | START WITH } int