时间:2021-07-01 10:21:17 帮助过:10人阅读
两个只是通过至少一个换行符的空白分隔的字符串常量会被连接在一起,并当做它们是写成一个常量处理。比如:
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_warning 和 backslash_quote 配置参数也影响字符串常量中反斜杠的处理。 |
编码为零的字符不允许出现在字符串常量中。
尽管声明字符串常量的标准方法通常都很方便,但是如果字符串中包含很多单引号或者反斜杠,那么理解字符串的内容可能就会变得很苦涩,因为每个单引号都要加倍。为了让这种场合下的查询更具可读性,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 标准,但是在写复杂的字符串文本的时候,它通常比标准的单引号语法更方便。尤其是在其它常量里表现字符串常量的时候更有用。比如在过程函数定义里,如果用单引号语法,每个上面例子里的每个反斜杠都必须写四个,它们在作为字符串文本分析的时候会减少为两个,然后在函数执行的时候在内层字符串常量里会再次被解析为一个。
位串常量看起来很像在开引号前面有一个 B(大写或小写)的普通字符串(它们之间没有空白),比如 B‘1001‘ 。位串常量里可以用的字符只有 0 和 1 。
另外,位串常量可以用十六进制表示法声明,方法是使用前缀 X(大写或者小写),比如 X‘1FF‘ ,其中的每个十六进制位等效于四个二进制位。
两种形式的位串常量都可以像普通字符串常量那样跨行连续。位串常量不能用美元符界定。
数值常量接受下列通用的形式:
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(历史的)风格
这些实际上只是下面讨论的通用转换的特例。
任意类型的常量都可以用下列表示法中的任何一种来输入:
type ‘string‘ ‘string‘::type CAST ( ‘string‘ AS type )
其中的 ‘string‘ 将会被转换为 type 类型的常量。如果不存在该常量所属类型的歧义,那么可以省略明确的类型转换(比如,当你把它直接赋予一个表字段的时候),这种情况下它会自动转换。
其中的 ‘string‘ 可以用普通 SQL 表示法或者美元符界定来书写。
我们还可以用函数风格的语法来声明类型转换:
typename ( ‘string‘ )
不过并非所有类型名都可以这样使用;参阅节4.2.8获取细节。
::, CAST() 和函数调用语法也可以用于声明任意表达式的运行时类型转换(如节4.2.8中讨论的那样)。但是 type ‘string‘ 的形式只能用于声明一个字面常量的类型。type ‘string‘ 的另外一个限制是它不能用于数组类型(要用 :: 或 CAST() 声明一个数组常量的类型)。
CAST() 语法遵循 SQL 标准。type ‘string‘ 语法是标准的一个推广:SQL 只是给少数几种数据类型声明了这个语法,但 PostgreSQL 允许将其用于所有类型。:: 和函数调用的语法是 PostgreSQL 的历史用法。
一个操作符是最多 NAMEDATALEN-1 个(缺省63个)下列字符的序列:
+ - * / < > = ~ ! @ # % ^ & | ` ?
不过,有几个限制:-- 和 /* 不能出现在操作符中的任何地方,因为它们会被当做注释开始对待。
多字符操作符不能以 + 或 - 结束,除非其中至少还包含下列操作符之一:
~ ! @ # % ^ & | ` ?
比如,@- 是允许的操作符,但 *- 不是。这个限制允许 PostgreSQL 在不要求记号之间有空白的情况下分析 SQL 兼容的查询。当你使用非 SQL 标准的操作符的时候,你通常需要用空白分隔相邻的操作符以避免歧义。比如,如果你定义了一个叫 @ 的左单目操作符,那么你就不能写成 X*@Y ;而是要写成 X* @Y 以确保 PostgreSQL 把它读成两个操作符,而不是一个。
有些非字母数字字符有一些特殊含义,因此不能用做操作符。它们的用法细节可以在相应的描述语法元素的地方找到。本节只是描述它们的存在和概括一下这些字符的目的。
美元符号($)后面跟着数字用于在一个函数体定义或者预备语句中表示参数的位置。在其它环境里美元符号可能是一个标识符名字或者是一个美元符界定的字符串常量的一部分。
圆括弧(())用于分组和强制优先级的时候含义与平常一样。有些场合里圆括弧是作为一个特定 SQL 命令的固定语法的一部分要求的。
方括弧([])用于选取数组元素。参阅节8.10获取更多信息。
逗号(,)在一些语法构造里用于分隔一个列表的元素。
分号(;)结束一条 SQL 命令。它不能出现在一条命令里的任何地方,除了在引号包围的字符串常量或者标识符中。
冒号(:)用于从数组中选取"片段"(参阅节8.10)。在一些 SQL 方言里(比如嵌入 SQL),冒号用于前缀变量名。
星号(*)在某些环境里表示一个表的全部字段或者一个复合类型的值。在用作聚集函数的参数时还表示该聚集并不需要明确的参数。
句点(.)用在数字常量里,并用于分隔模式、表、字段名。
注释是任意以双划线开头并延伸到行尾的任意字符序列,比如:
-- 这是标准的 SQL92 注释
另外,还可以使用C-风格的块注释:
/* 多行注释 * 可以嵌套: /* 被嵌套的块注释 */ */
这里注释以 /* 开头并扩展到对应的 */ 。这些块注释可以嵌套,就像 SQL99 里说的那样(但和 C 不一样),因此我们可以注释掉一大块已经包含块注释的代码。
注释在进一步的语法分析之前被从输入中流删除并用空白代替。
表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
PostgreSQL语法结构
标签: