PostgreSQL SQL 语言:函数和操作符
本文档为PostgreSQL 9.6.0文档,本转载已得到原译者彭煜玮授权。
常用的逻辑操作符有:
- AND
- OR
- NOT
SQL使用三值的逻辑系统,包括真、假和null,null表示"未知"。观察下面的真值表:
操作符AND和OR是可交换的,也就是说,你可以交换左右操作数而不影响结果。
常见的比较操作符都可用,如Table 9-1所示。
Note:
!=操作符在分析器阶段被转换成<>。不能把!=和<>操作符实现为做不同的事。
比较操作符可以用于所有可以比较的数据类型。所有比较操作符都是双目操作符,它们返回boolean类型;类似于1 < 2 < 3的表达式是非法的(因为没有<操作符可以比较一个布尔值和3)。
如Table 9-2所示,也有一些比较谓词。它们的行为和操作符很像,但是具有 SQL 标准所要求的特殊语法。
BETWEEN谓词可以简化范围测试:
a BETWEEN x AND y
等效于
a >= x AND a <= y
注意BETWEEN认为终点值是包含在范围内的。 NOT BETWEEN可以做相反比较:
a NOT BETWEEN x AND y
等效于
a < x OR a > y
BETWEEN SYMMETRIC和BETWEEN相似,不过BETWEEN SYMMETRIC不要求AND左边的参数小于或等于右边的参数。如果左参数不是小于等于右参数,这两个参数会自动被交换,这样总是会应用一个非空范围。
当有一个输入为空时,普通的比较操作符会得到空(表示"未知"),而不是真或假。例如,7 = NULL得到空,7 <> NULL也一样。如果这种行为不合适,可以使用IS [ NOT ] DISTINCT FROM谓词:
a IS DISTINCT FROM b
a IS NOT DISTINCT FROM b
对于非空输入,IS DISTINCT FROM和<>操作符一样。不过,如果两个输入都为空,它会返回假。而如果只有一个输入为空,它会返回真。类似地,IS NOT DISTINCT FROM对于非空输入的行为与=相同,但是当两个输入都为空时它返回真,并且当只有一个输入为空时返回假。因此,这些谓词实际上把空值当作一种普通数据值而不是"unknown"。
要检查一个值是否为空,使用下面的谓词:
expression IS NULL
expression IS NOT NULL
或者等效,但并不标准的谓词:
expression ISNULL
expression NOTNULL
不要写expression = NULL,因为NULL是不"等于"NULL的(控制代表一个未知的值,因此我们无法知道两个未知的数值是否相等)。
Tip: 有些应用可能要求表达式expression = NULL在expression得出空值时返回真。我们强烈建议这样的应用修改成遵循 SQL 标准。但是,如果这样修改不可能完成,那么我们可以使用配置变量transform_null_equals。如果打开它,PostgreSQL将把x = NULL子句转换成x IS NULL。
如果expression是行值,那么当行表达式本身为非空值或者行的所有域为非空时IS NULL为真。由于这种行为,IS NULL和IS NOT NULL并不总是为行值表达式返回反转的结果,特别是,一个同时包含 NULL 和非空值的域将会对两种测试都返回假。在某些情况下,写成row IS DISTINCT FROM NULL或者row IS NOT DISTINCT FROM NULL会更好,它们只会检查整个行值是否为空而不需要在行的域上做额外的测试。
布尔值也可以使用下列谓词进行测试:
boolean_expression IS TRUE
boolean_expression IS NOT TRUE
boolean_expression IS FALSE
boolean_expression IS NOT FALSE
boolean_expression IS UNKNOWN
boolean_expression IS NOT UNKNOWN
这些谓词将总是返回真或假,从来不返回空值,即使操作数是空也如此。空值输入被当做逻辑值"未知"。 请注意实际上IS UNKNOWN和IS NOT UNKNOWN分别与IS NULL和IS NOT NULL相同, 只是输入表达式必须是布尔类型。
如Table 9-3中所示,也有一些比较相关的函数可用。
PostgreSQL为很多类型提供了数学操作符。对于那些没有标准数学表达的类型(如日期/时间类型),我们将在后续小节中描述实际的行为。
Table 9-4展示了所有可用的数学操作符。
按位操作操作符只能用于整数数据类型,而其它的操作符可以用于全部数字数据类型。按位操作的操作符还可以用于位串类型bit和bit varying, 如Table 9-13所示。
Table 9-5显示了可用的数学函数。在该表中,dp表示double precision。这些函数中有许多都有多种不同的形式,区别是参数不同。除非特别指明,任何特定形式的函数都返回和它的参数相同的数据类型。 处理double precision数据的函数大多数是在宿主系统的 C 库基础上实现的;因此,边界情况下的准确度和行为是根据宿主系统而变化的。
Table 9-5. 数学函数
Table 9-6展示了用于产生随机数的函数。
random()返回的值的特征取决于系统实现。 它不适合用于加密应用,如果需要用于加密应用请参考pgcrypto模块。
最后,Table 9-7显示了可用的三角函数。所有三角函数都有类型为double precision的参数和返回类型。每一种三角函数都有两个变体,一个以弧度度量角,另一个以角度度量角。
Note:
另一种使用以角度度量的角的方法是使用早前展示的单位转换函数radians()和degrees()。不过,使用基于角度的三角函数更好,因为这类方法能避免sind(30)等特殊情况下的舍入偏差。
本节描述了用于检查和操作字符串值的函数和操作符。在这个环境中的串包括所有类型character、character varying和text的值。除非另外说明,所有下面列出的函数都可以处理这些类型,不过要小心的是,在使用character类型的时候, 它有自动填充空白的潜在影响。有些函数还可以处理位串类型。
SQL定义了一些字符串函数,它们使用关键字,而不是逗号来分隔参数。详情请见Table 9-8,PostgreSQL也提供了这些函数使用正常函数调用语法的版本(见Table 9-9)。
Note: 由于存在从那些数据类型到text的隐式强制措施,在PostgreSQL 8.3之前,这些函数也可以接受多种非字符串数据类型。这些强制措施在目前的版本中已经被删除,因为它们常常导致令人惊讶的行为。不过,字符串串接操作符(||)仍然接受非字符串输入,只要至少一个输入是一种字符串类型,如Table 9-8所示。对于其他情况,如果你需要复制之前的行为,可以为text插入一个显式强制措施。
Table 9-8. SQL字符串函数和操作符
还有额外的串操作函数可以用,它们在Table 9-9中列出。它们有些在内部用于实现Table 9-8列出的SQL标准字符串函数。
concat、concat_ws和format函数是可变的,因此可以把要串接或格式化的值作为一个标记了VARIADIC关键字的数组进行传递(见Section 36.4.5)。数组的元素被当作函数的独立普通参数一样处理。如果可变数组参数为 NULL,concat和concat_ws返回 NULL,但format把 NULL 当作一个零元素数组。
还可以参阅Section 9.20中的string_agg。
4.1 format
函数format根据一个格式字符串产生格式化的输出,其形式类似于 C 函数sprintf。
format(formatstr text [, formatarg "any" [, ...] ])
formatstr是一个格式字符串,它指定了结果应该如何被格式化。格式字符串中的文本被直接复制到结果中,除了使用格式说明符的地方。格式说明符在字符串中扮演着占位符的角色,它定义后续的函数参数如何被格式化及插入到结果中。每一个formatarg参数会被根据其数据类型的常规输出规则转换为文本,并接着根据格式说明符被格式化和插入到结果字符串中。
格式说明符由一个%字符开始并且有这样的形式
%[position][flags][width]type
其中的各组件域是:
position(可选)
一个形式为n$的字符串,其中n是要打印的参数的索引。索引 1 表示formatstr之后的第一个参数。如果position被忽略,默认会使用序列中的下一个参数。
flags(可选)
控制格式说明符的输出如何被格式化的附加选项。当前唯一支持的标志是一个负号(-),它将导致格式说明符的输出会被左对齐(left-justified)。除非width域也被指定,否者这个域不会产生任何效果。
width(可选)
指定用于显示格式说明符输出的最小字符数。输出将被在左部或右部(取决于-标志)用空格填充以保证充满该宽度。太小的宽度设置不会导致输出被截断,但是会被简单地忽略。宽度可以使用下列形式之一指定:一个正整数;一个星号(*)表示使用下一个函数参数作为宽度;或者一个形式为*n$的字符串表示使用第n个函数参数作为宽度。
如果宽度来自于一个函数参数,则参数在被格式说明符的值使用之前就被消耗掉了。如果宽度参数是负值,结果会在长度为abs(width)的域中被左对齐(如果-标志被指定)。
type(必需)
格式转换的类型,用于产生格式说明符的输出。支持下面的类型:
s将参数值格式化为一个简单字符串。一个控制被视为一个空字符串。
I将参数值视作 SQL 标识符,并在必要时用双写引号包围它。如果参数为空,将会是一个错误(等效于quote_ident)。
L将参数值引用为 SQL 文字。一个空值将被显示为不带引号的字符串NULL(等效于quote_nullable)。
除了以上所述的格式说明符之外,要输出一个文字形式的%字符,可以使用特殊序列%%。
下面有一些基本的格式转换的例子:
SELECT format('Hello %s', 'World');
结果:Hello World
SELECT format('Testing %s, %s, %s, %%', 'one', 'two', 'three');
结果:Testing one, two, three, %
SELECT format('INSERT INTO %I VALUES(%L)', 'Foo bar', E'O\'Reilly');
结果:INSERT INTO "Foo bar" VALUES('O''Reilly')
SELECT format('INSERT INTO %I VALUES(%L)', 'locations', E'C:\\Program Files');
结果:INSERT INTO locations VALUES(E'C:\\Program Files')
下面是使用width域和-标志的例子:
SELECT format('|%10s|', 'foo');
结果:| foo|
SELECT format('|%-10s|', 'foo');
结果:|foo |
SELECT format('|%*s|', 10, 'foo');
结果:| foo|
SELECT format('|%*s|', -10, 'foo');
结果:|foo |
SELECT format('|%-*s|', 10, 'foo');
结果:|foo |
SELECT format('|%-*s|', -10, 'foo');
结果:|foo |
这些例子展示了position域的例子:
SELECT format('Testing %3$s, %2$s, %1$s', 'one', 'two', 'three');
结果:Testing three, two, one
SELECT format('|%*2$s|', 'foo', 10, 'bar');
结果:| bar|
SELECT format('|%1$*2$s|', 'foo', 10, 'bar');
结果:| foo|
不同于标准的 C 函数sprintf,PostgreSQL的format函数允许将带有或者不带有position域的格式说明符被混在同一个格式字符串中。一个不带有position域的格式说明符总是使用最后一个被消耗的参数的下一个参数。另外,format函数不要求所有函数参数都被用在格式字符串中。例如:
SELECT format('Testing %3$s, %2$s, %s', 'one', 'two', 'three');
结果:Testing three, two, three
本节描述那些检查和操作类型为bytea的值的函数和操作符。
SQL定义了一些使用关键字而不是逗号来分割参数的串函数。详情请见Table 9-11。PostgreSQL也提供了这些函数使用常规函数调用语法的版本(参阅Table 9-12)。
Note: 本页中显示的示例结果假设服务器参数bytea_output被设置为escape(传统PostgreSQL格式)。
还有一些二进制串处理函数可以使用,在Table 9-12列出。 其中有一些是在内部使用,用于实现Table 9-11列出的 SQL 标准串函数。
get_byte和set_byte把一个二进制串中的一个字节计数为字节 0。get_bit和set_bit在每一个字节中从右边起计数位;例如位 0 是第一个字节的最低有效位,而位 15 是第二个字节的最高有效位。
本节描述用于检查和操作位串的函数和操作符,也就是操作类型为bit和bit varying的值的函数和操作符。除了常用的比较操作符之外,还可以使用Table 9-13里显示的操作符。&、|和#的位串操作数必须等长。在移位的时候,保留原始的位串的的长度,如例子所示。
下面的SQL标准函数除了可以用于字符串之外,也可以用于位串: length、 bit_length、 octet_length、 position、 substring、 overlay。
下面的函数除了可以用于二进制串之外,也可以用于位串: get_bit、 set_bit。 当使用于一个位串时,这些函数将串的第一(最左)位计数为位 0。
另外,我们可以在整数和bit之间来回转换。一些例子:
44::bit(10) 0000101100
44::bit(3) 100
cast(-44 as bit(12)) 111111010100
'1110'::bit(4)::integer 14
请注意,如果只是转换为"bit",意思是转换成bit(1),因此只会转换整数的最低有效位。
Note:
把一个整数转换成bit(n)将拷贝整数的最右边的n位。 把一个整数转换成比整数本身长的位串,就会在最左边扩展符号。
PostgreSQL提供了三种独立的实现模式匹配的方法:SQL LIKE操作符、更近一些的SIMILAR TO操作符(SQL:1999 里添加进来的)和POSIX-风格的正则表达式。除了这些基本的"这个串匹配这个模式吗?"操作符外,还有一些函数可用于提取或替换匹配子串并在匹配位置分离一个串。
Tip: 如果你的模式匹配的要求超出了这些,请考虑用 Perl 或 Tcl 写一个用户定义的函数。
Caution
虽然大部分的正则表达式搜索都能被很快地执行,但是正则表达式仍可能被 人为地弄成需要任意长的时间和任意量的内存进行处理。要当心从不怀好意 的来源接受正则表达式搜索模式。如果必须这样做,建议加上语句超时限制。
使用SIMILAR TO模式的搜索具有同样的安全性危险, 因为SIMILAR TO提供了很多和 POSIX-风格正则表达式相同的能力。
LIKE搜索比其他两种选项简单得多,因此在使用 不怀好意的模式来源时要更安全些。
9.7.1. LIKE
string LIKE pattern [ESCAPE escape-character]
string NOT LIKE pattern [ESCAPE escape-character]
如果该string匹配了提供的pattern,那么LIKE表达式返回真(和预期的一样,如果LIKE返回真,那么NOT LIKE表达式返回假, 反之亦然。一个等效的表达式是NOT (string LIKE pattern))。
如果pattern不包含百分号或者下划线,那么该模式只代表它本身的串;这时候LIKE的行为就象等号操作符。在pattern里的下划线 (_)代表(匹配)任何单个字符; 而一个百分号(%)匹配任何零或更多个字符的序列。
一些例子:
'abc' LIKE 'abc' true
'abc' LIKE 'a%' true
'abc' LIKE '_b_' true
'abc' LIKE 'c' false
LIKE模式匹配总是覆盖整个串。因此,要匹配在串内任何位置的序列,该模式必须以百分号开头和结尾。
要匹配文本的下划线或者百分号,而不是匹配其它字符, 在pattern里相应的字符必须 前导逃逸字符。缺省的逃逸字符是反斜线,但是你可以用ESCAPE子句指定一个不同的逃逸字符。 要匹配逃逸字符本身,写两个逃逸字符。
Note:
如果你关掉了standard_conforming_strings,你在文串常量中写的任何反斜线都需要被双写。
请注意反斜线在串文本里已经有特殊含义了,所以如果你写一个 包含反斜线的模式常量,那你就要在 SQL 语句里写两个反斜线。 因此,写一个匹配单个反斜线的模式实际上要在语句里写四个反斜线。 你可以通过用 ESCAPE 选择一个不同的逃逸字符 来避免这样;这样反斜线就不再是 LIKE 的特殊字符了。 但仍然是字符文本分析器的特殊字符,所以你还是需要两个反斜线。) 我们也可以通过写ESCAPE ''的方式不选择逃逸字符,这样可以有效地禁用逃逸机制,但是没有办法关闭下划线和百分号在模式中的特殊含义。
关键字ILIKE可以用于替换LIKE, 它令该匹配根据活动区域成为大小写无关。这个不属于SQL标准而是一个PostgreSQL扩展。
操作符~~ 等效于LIKE, 而~~ *对应ILIKE。 还有 !~~ 和!~~ *操作符分别代表NOT LIKE和NOT ILIKE。所有这些操作符都是PostgreSQL特有的。
9.7.2. SIMILAR TO正则表达式
string SIMILAR TO pattern [ESCAPE escape-character]
string NOT SIMILAR TO pattern [ESCAPE escape-character]
SIMILAR TO操作符根据自己的模式是否匹配给定串而返回真或者假。 它和LIKE非常类似,只不过它使用 SQL 标准定义的正则表达式理解模式。 SQL 正则表达式是在LIKE标记和普通的正则表达式标记的奇怪的杂交。
类似LIKE,SIMILAR TO操作符只有在它的模式匹配整个串的时候才能成功;这一点和普通的 正则表达式的行为不同,在普通的正则表达式里,模式匹配串的任意部分。 和LIKE类似的地方还有,SIMILAR TO使用_和%作为分别代表任意单个字符和任意串的通配符(这些可以比得上 POSIX 正则表达式里的.和.*)。
除了这些从LIKE借用的功能之外,SIMILAR TO支持下面这些从 POSIX 正则表达式借用的 模式匹配元字符:
- |表示选择(两个候选之一)。
- *表示重复前面的项零次或更多次。
- +表示重复前面的项一次或更多次。
- ?表示重复前面的项零次或一次。
- {m}表示重复前面的项刚好m次。
- {m,}表示重复前面的项m次或更多次。
- {m,n}表示重复前面的项至少m次并且不超过n次。
- 可以使用圆括号()把多个项组合成一个逻辑项。
- 一个方括号表达式[...]声明一个字符类,就像 POSIX 正则表达式一样。
注意点号(.)不是SIMILAR TO的一个元字符。
和LIKE一样,反斜线禁用所有这些元字符的特殊含义;当然我们也可以用ESCAPE指定一个不同的逃逸字符。
一些例子:
'abc' SIMILAR TO 'abc' true
'abc' SIMILAR TO 'a' false
'abc' SIMILAR TO '%(b|d)%' true
'abc' SIMILAR TO '(b|c)%' false
带三个参数的substring,即substring(string from pattern for escape-character),提供了抽取一个匹配 SQL 正则表达式的子串的方法。和SIMILAR TO一样,声明的模式必须匹配整个数据串,否则函数失败并返回空值。为了标识在成功的时候应该返回的模式部分,模式 必须包含逃逸字符的两次出现,并且后面要跟上双引号(")。匹配这两个标记之间的模式的文本将被返回。
一些例子,使用#"定界返回串:
substring('foobar' from '%#"o_b#"%' for '#') oob
substring('foobar' from '#"o_b#"%' for '#') NULL
9.7.3. POSIX正则表达式
Table 9-14列出了所有可用于 POSIX 正则表达式模式匹配的操作符。
Table 9-14. 正则表达式匹配操作符
POSIX正则表达式提供了比LIKE和SIMILAR TO操作符更强大的含义。许多 Unix 工具,例如egrep、sed或awk使用一种与我们这里描述的类似的模式匹配语言。
正则表达式是一个字符序列,它是定义一个串集合 (一个正则集)的缩写。 如果一个串是正则表达式描述的正则集中的一员时, 我们就说这个串匹配该正则表达式。 和LIKE一样,模式字符准确地匹配串字符, 除非在正则表达式语言里有特殊字符 — 不过正则表达式用的 特殊字符和LIKE用的不同。 和LIKE模式不一样的是,正则表达式允许匹配串里的任何位置,除非该正则表达式显式地挂接在串的开头或者结尾。
一些例子:
'abc' ~ 'abc' true
'abc' ~ '^a' true
'abc' ~ '(b|d)' true
'abc' ~ '^(b|c)' false
POSIX模式语言的详细描述见下文。
带两个参数的substring函数,即substring(string from pattern),提供了抽取一个匹配 POSIX 正则表达式模式的子串的方法。如果没有匹配它返回空值,否则就是文本中匹配模式的那部分。 但是如果该模式包含任何圆括号,那么将返回匹配第一对子表达式(对应第一个左圆括号的) 的文本。如果你想在表达式里使用圆括号而又不想导致这个例外,那么你可以在整个表达式外边放上一对圆括号。 如果你需要在想抽取的子表达式前有圆括号,参阅后文描述的非捕获性圆括号。
一些例子:
substring('foobar' from 'o.b') oob
substring('foobar' from 'o(.)b') o
regexp_replace函数提供了将匹配 POSIX 正则表达式模式的子串替换为新文本的功能。 它的语法是 regexp_replace(source, pattern, replacement [, flags ])。 如果没有匹配pattern,那么返回不加修改的source串。 如果有匹配,则返回的source串里面的匹配子串将被replacement串替换掉。replacement串可以包含\n, 其中\n是 1 到 9, 表明源串里匹配模式里第n个圆括号子表达式的子串应该被插入, 并且它可以包含&表示应该插入匹配整个模式的子串。如果你需要放一个文字形式的反斜线在替换文本里,那么写\。flags参数是一个可选的文本串,它包含另个或更多单字母标志,这些标志可以改变函数的行为。标志i指定大小写无关的匹配,而标志g指定替换每一个匹配的子串而不仅仅是第一个。支持的标志(但不是g)在Table 9-22中描述。
一些例子:
regexp_replace('foobarbaz', 'b..', 'X')
fooXbaz
regexp_replace('foobarbaz', 'b..', 'X', 'g')
fooXX
regexp_replace('foobarbaz', 'b(..)', E'X\\1Y', 'g')
fooXarYXazY
regexp_matches函数返回一个文本数组,该数组由匹配一个 POSIX 正则表达式模式得到的所有被捕获子串构成。其语法是regexp_matches(string, pattern [, flags ])。该函数可以不返回任何行、返回一行或者返回多行(见下文的g)。如果pattern不匹配,该函数不返回行。如果模式不包含圆括号子表达式,则每一个被返回的行都是一个单一元素的文本数组,其中包括匹配整个模式的子串。如果模式包含圆括号子表达式,该函数返回一个文本数组,它的第n个元素是匹配模式的第n个圆括号子表达式的子串("非捕获"圆括号不计算在内,详见下文)。flags参数是一个可选的文本字符串,它包含零个或更多个单字母标志,它们可以改变函数的行为。标志g让函数寻找串中的每一个匹配,而不仅仅是第一个,并且为每一个这样的匹配返回一行。支持的标志(但不是g)在Table 9-22中描述。
一些例子:
SELECT regexp_matches('foobarbequebaz', '(bar)(beque)');
regexp_matches
----------------
{bar,beque}
(1 row)
SELECT regexp_matches('foobarbequebazilbarfbonk', '(b[^b]+)(b[^b]+)', 'g');
regexp_matches
----------------
{bar,beque}
{bazil,barf}
(2 rows)
SELECT regexp_matches('foobarbequebaz', 'barbeque');
regexp_matches
----------------
{barbeque}
(1 row)
也可以强制regexp_matches()通过使用一个子选择来总是返回一行。当你希望所有行都被返回(甚至是不能匹配的行)时,把它用在一个SELECT目标列表中会特别有用:
SELECT col1, (SELECT regexp_matches(col2, '(bar)(beque)')) FROM tab;
regexp_split_to_table把一个 POSIX 正则表达式模式当作一个定界符来分离一个串。它的语法形式是regexp_split_to_table(string, pattern [, flags ])。如果没有与pattern的匹配,该函数返回string。如果有至少有一个匹配,对每一个匹配它都返回从上一个匹配的末尾(或者串的开头)到这次匹配开头之间的文本。当没有更多匹配时,它返回从上一次匹配的末尾到串末尾之间的文本。flags参数是一个可选的文本串,它包含零个或更多单字母标志,这些标识可以改变该函数的行为。regexp_split_to_table能支持的标志在Table 9-22中描述。
regexp_split_to_array函数的行为和regexp_split_to_table相同,不过regexp_split_to_array会把它的结果以一个text数组的形式返回。它的语法是regexp_split_to_array(string, pattern [, flags ])。这些参数和regexp_split_to_table的相同。
一些例子:
SELECT foo FROM regexp_split_to_table('the quick brown fox jumps over the lazy dog', E'\\s+') AS foo;
foo
-------
the
quick
brown
fox
jumps
over
the
lazy
dog
(9 rows)
SELECT regexp_split_to_array('the quick brown fox jumps over the lazy dog', E'\\s+');
regexp_split_to_array
-----------------------------------------------
{the,quick,brown,fox,jumps,over,the,lazy,dog}
(1 row)
SELECT foo FROM regexp_split_to_table('the quick brown fox', E'\\s*') AS foo;
foo
-----
t
h
e
q
u
i
c
k
b
r
o
w
n
f
o
x
(16 rows)
正如上一个例子所示,正则表达式分离函数会忽略零长度的匹配,这种匹配发生在串的开头或结尾或者正好发生在前一个匹配之后。这和正则表达式匹配的严格定义是相悖的,后者由regexp_matches实现,但是通常前者是实际中最常用的行为。其他软件系统如Perl也使用相似的定义。
7.3.1. 正则表达式细节
PostgreSQL的正则表达式是使用 Henry Spencer 写的一个包来实现的。下面的正则表达式的大部分描述都是从他的手册页中逐字拷贝过来的。
正则表达式(RE),在POSIX 1003.2 中定义, 它有两种形式:扩展的RE或者是ERE(大概地说就是那些在egrep里的), 基本的RE或者是BRE(大概地说就是那些在ed里的)。PostgreSQL支持两种形式,并且还实现了一些POSIX标准中没有但是在类似 Perl 或者 Tcl 这样的语言中得到广泛应用的一些扩展。使用了那些非POSIX扩展的RE叫高级RE, 或者本文档里说的ARE。ARE 几乎完全是 ERE 的超集,但是 BRE 有几个符号上的不兼容(以及更多的限制)。我们首先描述 ARE 和 ERE 形式, 描述那些只适用于 ARE 的特性,然后描述 BRE 的区别是什么。
Note:
PostgreSQL初始时总是推测一个正则表达式遵循 ARE 规则。但是,可以通过为 RE 模式预置一个embedded option来选择限制更多的 ERE 或 BRE 规则,如Section 9.7.3.4中所述。这对为期望准确的POSIX 1003.2 规则的应用提供兼容性很有用。
一个正则表达式被定义为一个或更多分支,它们之间被|分隔。只要能匹配其中一个分支的东西都能匹配正则表达式。
一个分支是一个或多个量化原子或者约束连接而成。一个原子匹配第一个,然后后面的原子匹配第二个, 以此类推;一个空分支匹配空串。
一个量化原子是一个原子, 后面可能跟着一个量词。没有量词的时候,它匹配一个原子, 有量词的时候,它可以匹配若干个原子。一个原子可以是在Table 9-15里面显示的任何可能。 可能的量词和它们的含义在Table 9-16里显示。
一个约束匹配一个空串,但只是在满足特定条件下才匹配。 约束可以在能够使用原子的地方使用,只是它不能跟着量词。简单的约束在Table 9-17里显示; 更多的约束稍后描述。
Table 9-15. 正则表达式原子
RE 不能以反斜线(\)结尾。
Note:
如果你关掉了standard_conforming_strings,任何你写在文字串常量中的反斜线都需要被双写。
Table 9-16. 正则表达式量词
使用{...}的形式被称作范围。 一个范围内的数字m和n都是无符号十进制整数, 允许的数值从 0 到 255(包含)。
非贪婪的量词(只在 ARE 中可用)匹配对应的正常 (贪婪)模式,区别是它寻找最少的匹配,而不是最多的匹配。详见Section 9.7.3.5。
Note: 一个量词不能紧跟在另外一个量词后面,例如**是非法的。量词不能作为表达式或者子表达式的开头,也不能跟在^或者|后面。
Table 9-17. 正则表达式约束
ookahead 和 lookbehind 约束不能包含后引用 (参阅Section 7.3.3),并且其中的所有圆括号 都被认为是非捕获的。
7.3.2. 方括号表达式
方括号表达式是一个包围在[]中的字符列表。它通常匹配列表中的任意单个字符(但见下文)。 如果列表以^开头,它匹配任意单个不在该列表参与部分中的字符。如果该列表中两个字符用-隔开, 那它就是那两个字符(包括在内)之间的所有字符范围的缩写,例如,在ASCII中[0-9]匹配任何十进制数字。两个范围共享一个端点是非法的,例如,a-c-e。范围与字符集关系密切, 可移植的程序应该避免依靠它们。
想在列表中包含文本],可以让它做列表的首字符(如果使用了^,需要放在其后)。 想在列表中包含文本-,可以让它做列表的首字符或者尾字符,或者一个范围的第二个端点。 想在列表中把文本-当做范围的起点, 把它用[.和.]包围起来,这样它就成为一个排序元素(见下文)。 除了这些字符本身、一些用[的组合(见下段)以及逃逸(只在 ARE 中有效)以外,所有其它特殊字符 在方括号表达式里都失去它们的特殊含义。特别是,在 ERE 和 BRE 规则下\不是特殊的, 但在 ARE 里,它是特殊的(引入一个逃逸)。
在一个方括号表达式里,一个排序元素(一个字符、一个被当做一个单一字符排序的多字符序列或者一个表示上面两种情况的排序序列名称) 包含在[.和.]里面的时候表示该排序元素的字符序列。该序列被当做该方括号列表 的一个单一元素。这允许一个包含多字符排序元素的方括号表达式去匹配多于一个字符,例如,如果排序序列包含一个ch排序元素, 那么 RE [[.ch.]]*c匹配chchcc的头五个字符。
Note:
PostgreSQL当前不支持多字符排序元素。这些信息描述了将来可能有的行为。
在方括号表达式里,包围在[=和=]里的排序元素是一个等价类, 代表等效于那一个的所有排序元素的字符序列,包括它本身(如果没有其它等效排序元素,那么就好象封装定界符是[.和 .])。例如,如果o和^是一个等价类的成员,那么[[=o=]]、[[=^=]]和[o^]都是同义的。一个等价类不能是一个范围的端点。
在方括号表达式里,在[:和:]里面封装的字符类的名字代表属于该类的所有字符的列表。 标准的字符类名字是:alnum、 alpha、blank、 cntrl、digit、 graph、lower、 print、punct、 space、upper、 xdigit。 它们代表在ctype中定义的字符类。 一个区域可以会提供其他的类。字符类不能用做一个范围的端点。
方括号表达式里有两个特例:方括号表达式[[:<:]]和[[:>:]]是约束,分别匹配一个单词开头和结束的空串。 单词定义为一个单词字符序列,前面和后面都没有其它单词字符。单词字符是一个alnum字符(和ctype中定义的一样) 或者一个下划线。这是一个扩展,兼容POSIX 1003.2, 但那里面并没有说明, 而且在准备移植到其他系统里去的软件里一定要小心使用。通常下文描述的约束逃逸更好些(它们并非更标准,但是更容易键入)。
7.3.3. 正则表达式逃逸
逃逸是以\开头,后面跟着一个字母数字字符得特殊序列。 逃逸有好几种变体:字符项、类缩写、约束逃逸以及后引用。在 ARE 里, 如果一个\后面跟着一个字母数字,但是并未组成一个合法的逃逸, 那么它是非法的。在 ERE 中没有逃逸:在方括号表达式之外,一个后面跟着字母数字字符的\只是表示该字符是一个普通的字符,而且在一个方括号表达式里,\是一个普通的字符(后者实际上在 ERE 和 ARE 不兼容)。
字符项逃逸用于便于我们在 RE 中声明那些不可打印的或其他习惯的字符。它们显示在Table 9-18中。
类缩写逃逸用来提供一些常用的字符类缩写。它们显示在Table 9-19中。
约束逃逸是一个约束,如果满足特定的条件,它匹配该空串。它们显示在Table 9-20中。
后引用(\n)匹配数字\n指定的被前面的圆括号子表达式匹配的同一个串 (参阅Table 9-21)。例如, ([bc])\1匹配bb或者cc, 但是不匹配bc或者cb。RE 中子表达式必须完全在后引用前面。子表达式以它们的先导圆括号的顺序编号。非捕获圆括号并不定义子表达式。
Table 9-18. 正则表达式字符项逃逸
十六进制位是0-9、a-f和A-F。八进制位是0-7。
指定 ASCII 范围(0-127)之外的值的数字字符项转义的含义取决于数据库编码。 当编码是 UTF-8 时,转义值等价于 Unicode 代码点,例如 \u1234表示字符U+1234。对于其他多字节编码, 字符项转义通常只是指定该字符的字节值的串接。如果该转义值不对应数据库编码 中的任何合法字符,将不会发生错误,但是它不会匹配任何数据。
字符项逃逸总是被当作普通字符。例如,\135是 ASCII 中的], 但\135并不终止一个方括号表达式。
Table 9-19. 正则表达式类缩写逃逸
在方括号表达式里,\d、\s和\w会失去它们的外层方括号,而\D、\S和 \W是非法的(也就是说,例如[a-c\d]等效于[a-c[:digit:]]。同样[a-c\D]等效于 [a-c^[:digit:]]的,也是非法的)。
Table 9-20. 正则表达式约束逃逸
一个词被定义成在上面[[:<:]]和[[:>:]]中的声明。在方括号表达式里,约束逃逸是非法的。
Note: 在八进制字符项逃逸和后引用之间有一个历史继承的歧义存在,这个歧义是 通过下面的启发式规则解决的,像上面描述地那样。前导零总是表示这是一个八进制逃逸。 而单个非零数字,如果没有跟着任何其它位,那么总是被认为后引用。 一个多位的非零开头的序列也被认为是后引用,只要它出现在合适的子表达式后面 (也就是说,在后引用的合法范围中的数),否则就被认为是一个八进制。
7.3.4. 正则表达式元语法
除了上面描述的主要语法之外,还有几种特殊形式和杂项语法。
如果一个 RE 以***:开头,那么剩下的 RE 都被当作 ARE(这在PostgreSQL中通常是无效的,因为 RE 被假定为 ARE,但是如果 ERE 或 BRE 模式通过flags参数被指定为一个正则表达式函数时,它确实能产生效果)。如果一个 RE 以***=开头, 那么剩下的 RE 被当作一个文本串,所有的字符都被认为是一个普通字符。
一个 ARE 可以以嵌入选项开头:一个序列(?xyz)(这里的xyz是一个或多个字母字符)声明影响剩余 RE 的选项。 这些选项覆盖任何前面判断的选项 — 特别地,它们可以覆盖一个正则表达式操作符隐含的大小写敏感的行为,或者覆盖flags参数中的正则表达式函数。可用的选项字母在Table 9-22中显示。注意这些同样的选项字母也被用在正则表达式函数的flags参数中。
嵌入选项在)终止序列时发生作用。它们只在 ARE 的开始处起作用 (在任何可能存在的***:控制器后面)。
除了通常的(紧)RE 语法(这种情况下所有字符都有效), 还有一种扩展语法,可以通过声明嵌入的x选项获得。在扩展语法里,RE 中的空白字符被忽略,就像那些在#和其后的新行(或 RE 的末尾)之间的字符一样。这样就允许我们给一个复杂的 RE 分段和注释。不过这个基本规则有三种例外:
- 空白字符或前置了\的#将被保留
- 方括号表达式里的空白或者#将被保留
- 在多字符符号里面不能出现空白和注释,例如(?:
为了这个目的,空白是空格、制表符、新行和任何属于空白字符类的字符。
最后,在 ARE 里,方括号表达式外面,序列(?#ttt)(其中ttt是任意不包含一个))的文本)是一个注释, 它被完全忽略。同样,这样的东西是不允许出现在多字符符号的字符中间的,例如 (?:。这种注释更像是一种历史产物而不是一种有用的设施,并且它们的使用已经被废弃;请使用扩展语法来替代。
如果声明了一个初始的***=控制器,那么所有这些元语法扩展都不能使用,因为这样表示把用户输入当作一个文字串而不是 RE 对待。
7.3.5. 正则表达式匹配规则
在 RE 可以在给定串中匹配多于一个子串的情况下, RE 匹配串中最靠前的那个子串。如果 RE 可以匹配在那个位置开始 的多个子串,要么是取最长的子串,要么是最短的,具体哪种, 取决于 RE 是贪婪的还是非贪婪的。
一个 RE 是否贪婪取决于下面规则:
- 大多数原子以及所有约束,都没有贪婪属性(因为它们毕竟无法匹配个数变化的文本)。
- 在一个 RE 周围加上圆括号并不会改变其贪婪性。
- 带一个固定重复次数量词 ({m}或者{m}?) 的量化原子和原子自身具有同样的贪婪性(可能是没有)。
- 一个带其他普通的量词(包括{m,n}中m等于n的情况)的量化原子是贪婪的(首选最长匹配)。
- 一个带非贪婪量词(包括{m,n}?中m等于 n的情况)的量化原子是非贪婪的(首选最短匹配)。
- 一个分支 — 也就是说,一个没有顶级|操作符的 RE — 和它里面的第一个有贪婪属性的量化原子有着同样的贪婪性。
- 一个由|操作符连接起来的两个或者更多分支组成的 RE 总是贪婪的。
上面的规则所描述的贪婪属性不仅仅适用于独立的量化原子, 而且也适用于包含量化原子的分支和整个 RE。这里的意思是, 匹配是按照分支或者整个 RE 作为一个整体匹配最长或者最短的可能子串。 一旦整个匹配的长度确定,那么匹配任意特定子表达式的部分就基于该子表达式的贪婪属性进行判断,在 RE 里面靠前的子表达式的优先级高于靠后的子表达式。
一个相应的例子:
SELECT SUBSTRING('XY1234Z', 'Y*([0-9]{1,3})');
结果:123
SELECT SUBSTRING('XY1234Z', 'Y*?([0-9]{1,3})');
结果:1
在第一个例子里,RE 作为整体是贪婪的,因为Y*是贪婪的。它可以匹配从Y开始的东西,并且它匹配从这个位置开始的最长的串, 也就是,Y123。输出是这里的圆括号包围的部分,或者说是123。在第二个例子里, RE 总体上是一个非贪婪的 RE,因为Y*?是非贪婪的。它可以匹配从Y开始的最短的子串,也就是说Y1。子表达式[0-9]{1,3}是贪婪的,但是它不能修改总体匹配长度的决定; 因此它被迫只匹配1。
简而言之,如果一个 RE 同时包含贪婪和非贪婪的子表达式,那么总的匹配长度要么是尽可能长,要么是尽可能短,这取决于给整个 RE 赋予的属性。给子表达式赋予的属性只影响在这个匹配里,各个子表达式之间相互允许"吃掉"的多少。
量词{1,1}和{1,1}?可以分别用于在一个子表达式 或者整个 RE 上强制贪婪或者非贪婪。当需要整个 RE 具有不同于从其元素中 推导出的贪婪属性时,这很有用。例如,假设我们尝试将一个包含一些数字的 字符串分隔成数字以及在它们之前和之后的部分,我们可能会尝试这样做:
SELECT regexp_matches('abc01234xyz', '(.*)(\d+)(.*)');
Result: {abc0123,4,xyz}
这不会有用:第一个.*是贪婪的,因此它会"吃掉" 尽可能多的字符而留下\d+去匹配在最后一个可能位置上的最 后一个数字。我们可能会通过让它变成非贪婪来修复:
SELECT regexp_matches('abc01234xyz', '(.*?)(\d+)(.*)');
Result: {abc,0,""}
这也不会有用:因为现在 RE 作为整体来说是非贪婪的,因此它会尽快结束 全部的匹配。我们可以通过强制 RE 整体是贪婪的来得到我们想要的:
SELECT regexp_matches('abc01234xyz', '(?:(.*?)(\d+)(.*)){1,1}');
Result: {abc,01234,xyz}
独立于 RE 的组件的贪婪性之外控制 RE 的整体贪婪性为处理变长模式提供了 很大的灵活性。
在决定更长或者更短的匹配时,匹配长度是以字符衡量的,而不是排序元素。一个空串会被认为比什么都不匹配长。例如:bb*匹配abbbc的中间三个字符;(week|wee)(night|knights)匹配weeknights的所有十个字符; 而(.*).*匹配 abc的时候,圆括号包围的子表达式匹配所有三个字符;当(a*)*被拿来匹配bc时,整个 RE 和圆括号 子表达式都匹配一个空串。
如果声明了大小写无关的匹配,那么效果就好像所有大小写区别在字母表中消失了。如果在多个情况中一个字母以一个普通字符的形式出现在方括号表达式外面,那么它实际上被转换成 一个包含大小写的方括号表达式,也就是说,x 变成 [xX]。 如果它出现在一个方括号表达式里面,那么它的所有大小写的同族都被加入 方括号表达式中,也就是说,x变成[xX]。当它出现在一个方括号表达式内时,它的所有大小写副本都被加入到方括号表达式中,例如, [x]会变成[xX],而[^x]会变成[^xX]。
如果指定了新行敏感的匹配,.和使用^的方括号表达式 将永远不会匹配新行字符(这样,匹配就绝对不会跨越新行,除非 RE 显式地安排了这样的情况)并且^和$除了分别匹配串开头和结尾之外,还将分别匹配新行后面和前面的空串。但是 ARE 逃逸\A和\Z仍然只匹配串的开头和结尾。
如果指定了部分新行敏感的匹配,那么它影响.和方括号表达式, 这个时候和新行敏感的匹配一样,但是不影响^和$。
如果指定了逆新行敏感匹配,那么它影响^和$,其作用和在新行敏感的匹配里一样,但是不影响.和方括号表达式。这个并不是很有用,只是为了满足对称性而提供的。
7.3.6. 限制和兼容性
在这个实现里,对 RE 的长度没有特别的限制。但是,那些希望高移植性的程序应该避免使用长度超过 256 字节的 RE,因为 POSIX 兼容 的实现可以拒绝接受这样的 RE。
ARE 实际上和 POSIX ERE 不兼容的唯一的特性是在方括号表达式里\并不失去它特殊的含义。所有其它 ARE 特性都使用在 POSIX ERE 里面是非法或者是未定义、未声明效果的语法;指示器的***就是在 POSIX 的 BRE 和 ERE 之外的语法。
许多 ARE 扩展都是从 Perl 那里借来的(但是有些被做了修改来清理它们),以及一些 Perl 里没有出现的扩展。要注意的不兼容性包括\b、\B、对结尾的新行缺乏特别的处理、对那些被新行敏感匹配的东西附加的补齐方括号表达式、在 lookahead/lookbehind 约束里对圆括号和后引用的限制以及最长/最短 匹配(而不是第一匹配)的语义。
PostgreSQL 7.4 之前的版本中识别的 ARE 和 ERE 语法存在两个非常明显的不兼容:
- 在 ARE 中,后面跟着一个字母数字字符的\要么是一个逃逸要么是一个错误, 但是在以前的版本里,它只是写该字母数字字符的另外一种方法。这个应该不是什么问题, 因为在以前的版本里没有什么理由会让我们写这样的序列。
- 在 ARE 里,\在[]里还是一个特殊字符, 因此在方括号表达式里的一个文本\必须被写成\。
7.3.7. 基本正则表达式
BRE 在几个方面和 ERE 不太一样。在 BRE 中,|、+和?都是普通字符并且没有与它们功能等价的东西。范围的定界符是\{和\}, 因为 {和}本身是普通字符。嵌套的子表达式的圆括号是\(和\),因为(和)自身是普通字符。除非在 RE 开头或者是圆括号子表达式开头,^都是一个普通字符。 除非在 RE 结尾或者是圆括号子表达式的结尾,$是一个普通字符。如果*出现在 RE 开头或者是圆括号封装的子表达式开头 (前面可能有^),那么它是个普通字符。最后,可以用单数字的后引用,\<和\>分别是[[:<:]]和[[:>:]]的同义词;在 BRE 中没有其它可用的逃逸。
PostgreSQL格式化函数提供一套强大的工具用于把各种数据类型 (日期/时间、整数、浮点、数字) 转换成格式化的字符串以及反过来从格式化的字符串转换成 指定的数据类型。Table 9-23列出了这些函数。这些函数都遵循一个公共的调用规范: 第一个参数是待格式化的值,而第二个是一个定义输出或输入格式的模板。
Table 9-23. 格式化函数
Note:
还有一个单一参数的to_timestamp函数,请见Table 9-30。
在一个to_char输出模板串中,一些特定的模式可以被识别并且被替换成基于给定值的被恰当地格式化的数据。任何不属于模板模式的文本都简单地照字面拷贝。同样,在一个输入 模板串里(对其他函数),模板模式标识由输入数据串提供的值。
Table 9-24展示了可以用于格式化日期和时间值的模版。
Table 9-24. 用于日期/时间格式化的模板模式
修饰语可以被应用于模板模式来修改它们的行为。例如,FMMonth就是带着FM修饰语的Month模式。Table 9-25展示了可用于日期/时间格式化的修饰语模式。
Table 9-25. 用于日期/时间格式化的模板模式修饰语
日期/时间格式化的使用须知:
- FM抑制前导的零或尾随的空白, 否则会把它们增加到输入从而把一个模式的输出变成固定宽度。在PostgreSQL中,FM只修改下一个声明,而在 Oracle 中,FM影响所有随后的声明,并且重复的FM修饰语将触发填充模式开和关。
- TM不包括结尾空白。to_timestamp和to_date会忽略TM修饰语。
- 如果没有使用FX选项,to_timestamp和to_date会跳过输入字符串中的多个空白。例如,to_timestamp('2000 JUN', 'YYYY MON')是正确的,但to_timestamp('2000 JUN', 'FXYYYY MON')会返回一个错误,因为to_timestamp只期望一个空白。FX必须被指定为模板中的第一个项。
- to_timestamp和to_date的存在是为了 处理无法被简单转换的输入格式。这些函数会从字面上解释输入,并做一点点错误检查。当 它们产生有效输出时,该转换可能得到意料之外的结果。例如,这些函数的输入没有被限制 在正常的范围内,因此to_date('20096040','YYYYMMDD')会返回 2014-01-17而不是报错。而造型不会有这样的行为。
- 在to_char模板里可以有普通文本,并且它们会被照字面输出。你可以把一个子串放到双引号里强迫它被解释成一个文本,即使它里面包含模式关键字也如此。例如,在 '"Hello Year "YYYY'中,YYYY将被年份数据代替,但是Year中单独的Y不会。在to_date、to_number和to_timestamp中,双引号字符串会跳过包含在字符串中字符个数的字符,例如"XX"跳过两个输入字符。
- 如果你想在输出里有双引号,那么你必须在它们前面放反斜线,例如 '\"YYYY Month\"'。
- 如果年份格式声明少于四位(如YYY)并且提供的年份少于四位,年份将被调整为最接近于 2020 年,例如95会变成 1995。
- 在处理长于 4 位的年份时,从字串向timestamp或者date的YYYY转换有一个限制。你必须在YYYY后面使用一些非数字字符或者模板, 否则年份总是被解释为 4 位数字。例如(对于 20000 年):to_date('200001131', 'YYYYMMDD')将会被解释成一个 4 位数字的年份,而不是在年份后使用一个非数字分隔符,像to_date('20000-1131', 'YYYY-MMDD')或to_date('20000Nov31', 'YYYYMonDD')。
- 在从字符串向timestamp或date的转换中, 如果有YYY、YYYY或者Y,YYY域, 那么CC(世纪)域会被忽略。如果CC和YY或Y一起使用, 那么年份被计算时会认为年份位于指定的世纪中。如果该世纪被指定但是年份没有被指定,将假定用该世纪的第一年。
- 一个 ISO 8601 周编号的日期(与一个格里高利日期相区别)可以用两种方法之一被指定为to_timestamp和to_date:
- 年、周编号和工作日:例如to_date('2006-42-4', 'IYYY-IW-ID')返回日期2006-10-19。如果你忽略工作日,它被假定为 1(周一)。
- 年和一年中的日:例如to_date('2006-291', 'IYYY-IDDD')也返回2006-10-19。
尝试使用一个混合了 ISO 8601 周编号和格里高利日期的域来输入一个日期是无意义的,并且将导致一个错误。在一个 ISO 周编号的年的环境下,一个"月"或"月中的日"的概念没有意义。在一个格里高利年的环境下,ISO 周没有意义。用户应当避免混合格里高利和 ISO 日期声明。
Caution
虽然to_date将会拒绝混合使用格里高利和 ISO 周编号日期的域, to_char却不会,因为YYYY-MM-DD (IYYY-IDDD) 这种输出格式也会有用。但是避免写类似IYYY-MM-DD的东西,那会得到在 起始年附近令人惊讶的结果。
- 在从字符串到timestamp的转换中,毫秒(MS)和微秒(US)值都被用作小数点后的秒位。例如to_timestamp('12:3', 'SS:MS')不是 3 毫秒, 而是 300,因为该转换把它看做 12 + 0.3 秒。这意味着对于格式SS:MS而言,输入值12:3、12:30和12:300指定了相同数目的毫秒。要得到三毫秒,你必须使用 12:003,转换会把它看做 12 + 0.003 = 12.003 秒。
下面是一个更复杂的例子∶to_timestamp('15:12:02.020.001230', 'HH:MI:SS.MS.US')是 15 小时、12 分钟和 2 秒 + 20 毫秒 + 1230微秒 = 2.021230 秒。
- to_char(..., 'ID')的一周中日的编号匹配extract(isodow from ...)函数,但是to_char(..., 'D')不匹配extract(dow from ...)的日编号。
- to_char(interval)格式化HH和HH12为显示在一个 12 小时的时钟上,即零小时和 36 小时输出为12,而HH24会输出完整的小时值,对于间隔它可以超过 23.
Table 9-26展示了可以用于格式化数字值的模版模式。
Table 9-26. 用于数字格式化的模板模式
数字格式化的用法须知:
- 使用SG、PL或MI格式化的符号并不挂在数字上面; 例如,to_char(-12, 'MI9999')生成'- 12',而to_char(-12, 'S9999')生成 ' -12'。Oracle 里的实现不允许在9前面使用MI,而是要求9在MI前面。
- 9导致一个值,这个值的位数好像有那么多个9在那里。如果一个数字不可用,它将输出一个空格。
- TH不会转换小于零的数值,也不会转换小数。
- PL、SG和TH是PostgreSQL扩展。
- 带有to_char的V会把输入值乘上10^n,其中n是跟在V后面的位数。带有to_number的V以类似的方式做除法。to_char和to_number不支持使用结合小数点的V(例如,不允许99.9V99)。
- EEEE(科学记数法)不能和任何其他格式化模式或修饰语(数字和小数点模式除外)组合在一起使用,并且必须位于格式化字符串的最后(例如9.99EEEE是一个合法的模式)。
- 某些修饰语可以被应用到任何模板来改变其行为。例如,FM9999是带有FM修饰语的9999模式。Table 9-27中展示了用于数字格式化模式修饰语。
Table 9-27. 用于数字格式化的模板模式修饰语
Table 9-28展示了一些使用to_char函数的例子。
Table 9-28. to_char例子
Table 9-30展示了可用于处理日期/时间值的函数,其细节在随后的小节中描述。Table 9-29演示了基本算术操作符 (+、*等)的行为。 而与格式化相关的函数。
所有下文描述的接受time或timestamp输入的函数和操作符实际上都有两种变体: 一种接收time with time zone或timestamp with time zone, 另外一种接受time without time zone或者 timestamp without time zone。为了简化,这些变种没有被独立地展示。此外,+和*操作符都是可交换的操作符对(例如,date + integer 和 integer + date);我们只显示其中一个。
Table 9-29. 日期/时间操作符
Table 9-30. 日期/时间函数
除了这些函数以外,还支持 SQL 操作符OVERLAPS:
(start1, end1) OVERLAPS (start2, end2)
(start1, length1) OVERLAPS (start2, length2)
这个表达式在两个时间域(用它们的端点定义)重叠的时候得到真,当它们不重
最后更新:2017-08-17 19:33:03