打印

PostgreSQL 8.1 中文文档

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

4.1.2.1. 字符串常量
SQL 里的一个字串文本是用单引号(')包围的任意字符序列, 比如,'This is a string'。 这种声明字串常量的方法是 SQL 标准定义的。 在这种类型的字串常量里嵌入单引号的标准兼容的做法是敲入两个连续的单引号比如,'Dianne''s horse'。 另外,PostgreSQL 允许用用一个反斜杠("\'")来逃逸单引号, 因此同一个字串可以写成'Dianne\'s horse'。 不过,将来版本的 PostgreSQL 将不允许这么用, 所以使用反斜扛的应用应该转换成上面说的标准兼容的方法。

另外一个 PostgreSQL 扩展是还可以使用 C-风格的反斜杠逃逸: \b 是一个退格,\f 是一个进纸,\n 是一个换行符, \r 是一个回车,\t 是一个水平制表符。 还支持 \digits, 这里 digits 是一个八进制字节数值, 还支持 \xhexdigits, 这里的 hexdigits 代表十六进制字节值。 (你创建的字节序列是否服务器的字符集编码能接受的正确字符,是你自己的责任。) 任何其它跟在反斜杠后面的字符都当做文本看待。 因此,要在字符串常量里包含反斜杠,则写两个反斜杠。

注意: 虽然现在的普通字串支持 C 风格的反斜扛逃逸, 将来版本讲对这样使用发出警告,并且最后将认为反斜扛是标准兼容的文本字符。 声明逃逸处理的比较好的方法是使用逃逸字串语法,表示需要进行逃逸处理。 逃逸字串语法是通过在字串前写字母 E (大写或者小写)的方法声明的。 比如,E'\041'。这个方法将在所有将来版本的 PostgreSQL 里起作用。

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

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

SELECT 'foo'
'bar';等效于

SELECT 'foobar';而

SELECT 'foo'      'bar';是非法的语法,(这个略微有些怪异的行为是 SQL 声明的; PostgreSQL 遵循标准。)

TOP

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

$$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$ 不对。

一个后面跟着关键字或者标识符的美元包围的字串必须用空白隔开; 否则美元符包围分隔符将会被认为前面标识符的一部分。

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

TOP

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

另外,位串常量可以用十六进制表示法声明,方法是使用前缀的 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 (历史原因)风格
     这些实际上只是下面讨论的通用转换的特例。

TOP

4.1.2.5. 其它类型的常量
任意类似的常量可以用下列表示法中的任何一种来输入:

type 'string'
'string'::type
CAST ( 'string' AS type )在字串常量的文本将传递给那种叫 type 的类型的输入转换过程。 结果是这种类型的一个常量。如果不存在该常量所属类型的歧义, 那么明确的类型映射可以省略(比如,当你把它直接赋予一个表字段的时候), 这种情况下它会自动转换。

字串常量可以用普通 SQL 表示法或者美元符包围来书写。

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

typename ( 'string' )不过并非所有类型名可以这样使用;参阅 Section 4.2.8 获取细节。

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

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

TOP

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

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

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


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

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

~ ! @ # % ^ & | ` ?

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


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

TOP

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



美元符号($)后面跟着数字用于在一个函数体定义或者准备好的语句中 表示参数的位置。在其他环境里美元符号可能是一个标识符名字或者是一个美元符包围的字串常量的一部分。

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

方括弧([])用于选取数组元素。 参阅 Section 8.10 获取更多信息。

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

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

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

星号 (* 在某些环境里表示一个表行或者一个符合类型值的全部字段。 在用作聚集函数 COUNT 的参数时还有特殊含义。

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


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

-- 这是标准的 SQL92 注释
另外,还可以使用 C-风格的块注释:

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

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

TOP

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

SELECT 5 ! - 6;会被分析成

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

SELECT (5 !) - 6;这是我们为扩展性付出的代价。

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

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

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

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

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

TOP

--------------------------------------------------------------------------------

4.2. 值表达式
值表达式用在各种语法环境中,比如在 SELECT 命令的目标列表中,在 INSERT 或 UPDATE 中用做新的列值,或者在许多命令中的搜索条件中使用。 我们有时候把值表达式的结果叫做标量, 以便与一个表表达式的结果相区别(是一个表)。因此值表达式也叫做标量表达式 (或者更简单的表达式)。表达式语法允许对来自基本部分的数值进行算术,逻辑,集合,和其它操作的运算。

值表达式是下列内容之一:



一个常量或者文本值。

一个字段引用。

一个位置参数引用,在函数声明体中。

一个操作符调用。

一个函数调用。

一个聚集表达式。

一个类型转换。

一个标量子查询。

一个行构造器。

另外一个在圆括弧里面的值表达式,可以用于子表达式分组和覆盖优先级。


除了这个列表以外,还有许多构造可以归类为表达式,但是不遵循任何通用的语法规则。 它们通常有函数或操作符的语义,并且在 Chapter 9 里合适的位置描述。 一个例子是 IS NULL 子句。

我们已经在 Section 4.1.2 里有讨论过的内容了。下面的节讨论剩下的选项。

4.2.1. 字段引用
一个字段可以用下面形式的引用:

correlation.columnname
correlation 是一个表的名字(可能有模式修饰), 或者是用FROM子句这样的方法定义的表的别名,或者是关键字 NEW 或 OLD。 (NEW和 OLD只能出现在一条改写规则中, 而其他相关的名字可以用于任意 SQL 语句中。) 如果在当前查询中所使用的所有表中,该字段名字是唯一的, 那么这个相关名字和分隔用的点就可以省略。 (又见 Chapter 7。)

4.2.2. 位置参数
位置参数引用用于标识从外部给一个 SQL 语句的一个参数。 参数用于 SQL 函数定义语句和准备好的查询。 有些客户端库还支持在 SQL 命令字串外边声明数据值,这种情况下参数用于引用 SQL 字串行外的数据。 一个参数的形式如下:

$number
比如,看看一个函数 dept 的定义, 如下

CREATE FUNCTION dept(text) RETURNS dept
  AS $$ SELECT * FROM dept WHERE name = $1 $$
  LANGUAGE SQL;在函数被调用的时候这里的 $1 将引用第一个函数的参数。

TOP

4.2.3. 下标
如果一个表达式生成一个数组类型的数值,那么我们可以通过写下面这样的表达式来声明数组值的元素

expression[subscript]如果是多个相邻的元素(一个"数组片断")可以用下面的方法抽取

expression[lower_subscript:upper_subscript](在这里,方括弧 [ ] 的意思是按照字面文本的方式出现。) 每个subscript自己都是一个表达式,它必须生成一个整数值。

通常,数组 expression 必须用圆括弧包围, 但如果要进行脚标计算的表达式只是一个字段引用或者一个位置参数,那么圆括弧可以省略。 同样,如果源数组是多维的,那么多个脚标可以连接在一起。比如,

mytable.arraycolumn[4]
mytable.two_d_column[17][34]
$1[10:42]
(arrayfunction(a,b))[42]最后一个例子里的圆括弧是必须的。参阅 Section 8.10 获取有关数组的更多信息。

4.2.4. 字段选择
如果一个表达式生成一个复合类型(行类型),那么用下面的方法可以抽取一个指定的字段

expression.fieldname
通常,行 expression 必须用圆括弧包围, 但是如果要选取的表达式只是一个表引用或者位置参数,可以省略圆括弧。 比如

mytable.mycolumn
$1.somecolumn
(rowfunction(a,b)).col3(因此,一个全称的字段引用实际上只是一个字段选择语法的特例。)

TOP

4.2.5. 操作符调用
操作符调用有三种语法∶


expression operator expression (双目中缀操作符)
operator expression (单目前缀操作符)
expression operator (单目后缀操作符)


这里的 operator 记号遵循语法规则: Section 4.1.3, 或者是记号:AND, OR,和 NOT 之一。 或者是一个被修饰的操作符名

OPERATOR(schema.operatorname)具体存在哪个操作符以及它们是单目还是双目取决于系统或用户定义了什么操作符。Chapter 9 描述了内置的操作符。

4.2.6. 函数调用
函数调用的语法是合法函数名字(可能有模式名修饰), 后面跟着在圆括弧里的它的参数列表:

function ([expression [, expression ... ]] )
比如,下面的代码计算 2 的平方根:

sqrt(2)
内置函数的列表在 Chapter 9 里。 其它函数可以由用户添加。

4.2.7. 聚集表达式
一个聚集表达式代表一个聚集函数对一个查询选出的行的处理。 一个聚集函数把多个输入缩减为一个输出值, 比如给输入求和或平均。一个聚集表达式的语法是下列之一:

aggregate_name (expression)
aggregate_name (ALL expression)
aggregate_name (DISTINCT expression)
aggregate_name ( * )这里 aggregate_name 是前面定义的聚集,(可能是全称), 而 expression 是一个本身不包含聚集表达式的任意值表达式。

第一种形式的聚集表达式为所有表达式生成非空值的输入行调用聚集。 (实际上,是否忽略空值由聚集函数决定 — 但是所有标准的聚集函数都忽略它们。) 第二种形式和第一种一样,因为 ALL 是缺省值。 第三种形式为所有输入行里找到表达式的所有唯一的非空值调用聚集。 最后一种形式为每个输入行(不管是空还是非空)调用一次聚集; 因为没有声明特定的输入值。通常它只是对 count() 聚集函数有用。

比如,count(*) 生成输入行的总数; count(f1) 生成 f1 为非空的输入行数; count(distinct f1) 生成 f1 唯一非空的行数。

预定义的聚集函数在 Section 9.15 里描述。 其它聚集函数可以由用户增加。

一个聚集表达式只能在 SELECT 命令的结果列表或者 HAVING 子句里出现。 禁止在其它子句里出现,比如 WHERE 里面,因为这些子句逻辑上在生成聚集结果之前计算。

如果一个聚集表达式出现在一个子查询里(参阅 Section 4.2.9 和 Section 9.16), 聚集通常是在子查询的行上进行计算。但是如果聚集的参数只包含外层查询的变量则有一个例外: 这个聚集会属于离他最近的外层查询,并且在该查询上进行计算。 该聚集表达式整体上属于它出现的子查询对外层查询的引用,其作用相当于子查询任何一次计算中的一个常量。 这个聚集表达式的有关只能出现在结果列或者 HAVING 子句的限制适用于聚集所属的查询层。

TOP


感谢一直以来您对我们的支持!
当前时区 GMT+8, 现在时间是 2008-12-3 04:01 京ICP证060528 号

Designed By 17DST