PostgreSQLSQL语言:函数和操作符

丰富的线上&线下活动,深入探索云世界

做任务,得社区积分和周边

最真实的开发者用云体验

让每位学生受益于普惠算力

让创作激发创新

资深技术专家手把手带教

遇见技术追梦人

技术交流,直击现场

海量开发者使用工具、手册,免费下载

极速、全面、稳定、安全的开源镜像

开发手册、白皮书、案例集等实战精华

为开发者定制的Chrome浏览器插件

1.逻辑操作符

常用的逻辑操作符有:

操作符AND和OR是可交换的,也就是说,你可以交换左右操作数而不影响结果。

2.比较函数和操作符

常见的比较操作符都可用,如Table9-1所示。

Note:!=操作符在分析器阶段被转换成<>。不能把!=和<>操作符实现为做不同的事。

比较操作符可以用于所有可以比较的数据类型。所有比较操作符都是双目操作符,它们返回boolean类型;类似于1<2<3的表达式是非法的(因为没有<操作符可以比较一个布尔值和3)。

如Table9-2所示,也有一些比较谓词。它们的行为和操作符很像,但是具有SQL标准所要求的特殊语法。

BETWEEN谓词可以简化范围测试:

aBETWEENxANDy等效于

a>=xANDa<=y注意BETWEEN认为终点值是包含在范围内的。NOTBETWEEN可以做相反比较:

aNOTBETWEENxANDy等效于

ayBETWEENSYMMETRIC和BETWEEN相似,不过BETWEENSYMMETRIC不要求AND左边的参数小于或等于右边的参数。如果左参数不是小于等于右参数,这两个参数会自动被交换,这样总是会应用一个非空范围。

当有一个输入为空时,普通的比较操作符会得到空(表示"未知"),而不是真或假。例如,7=NULL得到空,7<>NULL也一样。如果这种行为不合适,可以使用IS[NOT]DISTINCTFROM谓词:

aISDISTINCTFROMbaISNOTDISTINCTFROMb对于非空输入,ISDISTINCTFROM和<>操作符一样。不过,如果两个输入都为空,它会返回假。而如果只有一个输入为空,它会返回真。类似地,ISNOTDISTINCTFROM对于非空输入的行为与=相同,但是当两个输入都为空时它返回真,并且当只有一个输入为空时返回假。因此,这些谓词实际上把空值当作一种普通数据值而不是"unknown"。

要检查一个值是否为空,使用下面的谓词:

expressionISNULLexpressionISNOTNULL或者等效,但并不标准的谓词:

expressionISNULLexpressionNOTNULL不要写expression=NULL,因为NULL是不"等于"NULL的(控制代表一个未知的值,因此我们无法知道两个未知的数值是否相等)。

Tip:有些应用可能要求表达式expression=NULL在expression得出空值时返回真。我们强烈建议这样的应用修改成遵循SQL标准。但是,如果这样修改不可能完成,那么我们可以使用配置变量transform_null_equals。如果打开它,PostgreSQL将把x=NULL子句转换成xISNULL。

如果expression是行值,那么当行表达式本身为非空值或者行的所有域为非空时ISNULL为真。由于这种行为,ISNULL和ISNOTNULL并不总是为行值表达式返回反转的结果,特别是,一个同时包含NULL和非空值的域将会对两种测试都返回假。在某些情况下,写成rowISDISTINCTFROMNULL或者rowISNOTDISTINCTFROMNULL会更好,它们只会检查整个行值是否为空而不需要在行的域上做额外的测试。

布尔值也可以使用下列谓词进行测试:

boolean_expressionISTRUEboolean_expressionISNOTTRUEboolean_expressionISFALSEboolean_expressionISNOTFALSEboolean_expressionISUNKNOWNboolean_expressionISNOTUNKNOWN这些谓词将总是返回真或假,从来不返回空值,即使操作数是空也如此。空值输入被当做逻辑值"未知"。请注意实际上ISUNKNOWN和ISNOTUNKNOWN分别与ISNULL和ISNOTNULL相同,只是输入表达式必须是布尔类型。

3.数学函数和操作符

Table9-4展示了所有可用的数学操作符。

按位操作操作符只能用于整数数据类型,而其它的操作符可以用于全部数字数据类型。按位操作的操作符还可以用于位串类型bit和bitvarying,如Table9-13所示。

Table9-5显示了可用的数学函数。在该表中,dp表示doubleprecision。这些函数中有许多都有多种不同的形式,区别是参数不同。除非特别指明,任何特定形式的函数都返回和它的参数相同的数据类型。处理doubleprecision数据的函数大多数是在宿主系统的C库基础上实现的;因此,边界情况下的准确度和行为是根据宿主系统而变化的。

Table9-5.数学函数

Table9-6展示了用于产生随机数的函数。

random()返回的值的特征取决于系统实现。它不适合用于加密应用,如果需要用于加密应用请参考pgcrypto模块。

最后,Table9-7显示了可用的三角函数。所有三角函数都有类型为doubleprecision的参数和返回类型。每一种三角函数都有两个变体,一个以弧度度量角,另一个以角度度量角。

Note:另一种使用以角度度量的角的方法是使用早前展示的单位转换函数radians()和degrees()。不过,使用基于角度的三角函数更好,因为这类方法能避免sind(30)等特殊情况下的舍入偏差。

4.字符串函数和操作符

本节描述了用于检查和操作字符串值的函数和操作符。在这个环境中的串包括所有类型character、charactervarying和text的值。除非另外说明,所有下面列出的函数都可以处理这些类型,不过要小心的是,在使用character类型的时候,它有自动填充空白的潜在影响。有些函数还可以处理位串类型。

SQL定义了一些字符串函数,它们使用关键字,而不是逗号来分隔参数。详情请见Table9-8,PostgreSQL也提供了这些函数使用正常函数调用语法的版本(见Table9-9)。

Note:由于存在从那些数据类型到text的隐式强制措施,在PostgreSQL8.3之前,这些函数也可以接受多种非字符串数据类型。这些强制措施在目前的版本中已经被删除,因为它们常常导致令人惊讶的行为。不过,字符串串接操作符(||)仍然接受非字符串输入,只要至少一个输入是一种字符串类型,如Table9-8所示。对于其他情况,如果你需要复制之前的行为,可以为text插入一个显式强制措施。

Table9-8.SQL字符串函数和操作符

还有额外的串操作函数可以用,它们在Table9-9中列出。它们有些在内部用于实现Table9-8列出的SQL标准字符串函数。

concat、concat_ws和format函数是可变的,因此可以把要串接或格式化的值作为一个标记了VARIADIC关键字的数组进行传递(见Section36.4.5)。数组的元素被当作函数的独立普通参数一样处理。如果可变数组参数为NULL,concat和concat_ws返回NULL,但format把NULL当作一个零元素数组。

还可以参阅Section9.20中的string_agg。

4.1format

函数format根据一个格式字符串产生格式化的输出,其形式类似于C函数sprintf。

format(formatstrtext[,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)。

除了以上所述的格式说明符之外,要输出一个文字形式的%字符,可以使用特殊序列%%。

下面有一些基本的格式转换的例子:

SELECTformat('Hello%s','World');结果:HelloWorldSELECTformat('Testing%s,%s,%s,%%','one','two','three');结果:Testingone,two,three,%SELECTformat('INSERTINTO%IVALUES(%L)','Foobar',E'O\'Reilly');结果:INSERTINTO"Foobar"VALUES('O''Reilly')SELECTformat('INSERTINTO%IVALUES(%L)','locations',E'C:\\ProgramFiles');结果:INSERTINTOlocationsVALUES(E'C:\\ProgramFiles')下面是使用width域和-标志的例子:

SELECTformat('|%10s|','foo');结果:|foo|SELECTformat('|%-10s|','foo');结果:|foo|SELECTformat('|%*s|',10,'foo');结果:|foo|SELECTformat('|%*s|',-10,'foo');结果:|foo|SELECTformat('|%-*s|',10,'foo');结果:|foo|SELECTformat('|%-*s|',-10,'foo');结果:|foo|这些例子展示了position域的例子:

SELECTformat('Testing%3$s,%2$s,%1$s','one','two','three');结果:Testingthree,two,oneSELECTformat('|%*2$s|','foo',10,'bar');结果:|bar|SELECTformat('|%1$*2$s|','foo',10,'bar');结果:|foo|不同于标准的C函数sprintf,PostgreSQL的format函数允许将带有或者不带有position域的格式说明符被混在同一个格式字符串中。一个不带有position域的格式说明符总是使用最后一个被消耗的参数的下一个参数。另外,format函数不要求所有函数参数都被用在格式字符串中。例如:

SELECTformat('Testing%3$s,%2$s,%s','one','two','three');结果:Testingthree,two,three5.二进制串函数和操作符

本节描述那些检查和操作类型为bytea的值的函数和操作符。

SQL定义了一些使用关键字而不是逗号来分割参数的串函数。详情请见Table9-11。PostgreSQL也提供了这些函数使用常规函数调用语法的版本(参阅Table9-12)。

Note:本页中显示的示例结果假设服务器参数bytea_output被设置为escape(传统PostgreSQL格式)。

还有一些二进制串处理函数可以使用,在Table9-12列出。其中有一些是在内部使用,用于实现Table9-11列出的SQL标准串函数。

get_byte和set_byte把一个二进制串中的一个字节计数为字节0。get_bit和set_bit在每一个字节中从右边起计数位;例如位0是第一个字节的最低有效位,而位15是第二个字节的最高有效位。

6.位串函数和操作符

本节描述用于检查和操作位串的函数和操作符,也就是操作类型为bit和bitvarying的值的函数和操作符。除了常用的比较操作符之外,还可以使用Table9-13里显示的操作符。&、|和#的位串操作数必须等长。在移位的时候,保留原始的位串的的长度,如例子所示。

下面的SQL标准函数除了可以用于字符串之外,也可以用于位串:length、bit_length、octet_length、position、substring、overlay。

下面的函数除了可以用于二进制串之外,也可以用于位串:get_bit、set_bit。当使用于一个位串时,这些函数将串的第一(最左)位计数为位0。

另外,我们可以在整数和bit之间来回转换。一些例子:

44::bit(10)000010110044::bit(3)100cast(-44asbit(12))111111010100'1110'::bit(4)::integer14请注意,如果只是转换为"bit",意思是转换成bit(1),因此只会转换整数的最低有效位。

Note:把一个整数转换成bit(n)将拷贝整数的最右边的n位。把一个整数转换成比整数本身长的位串,就会在最左边扩展符号。

7.模式匹配

PostgreSQL提供了三种独立的实现模式匹配的方法:SQLLIKE操作符、更近一些的SIMILARTO操作符(SQL:1999里添加进来的)和POSIX-风格的正则表达式。除了这些基本的"这个串匹配这个模式吗?"操作符外,还有一些函数可用于提取或替换匹配子串并在匹配位置分离一个串。

Tip:如果你的模式匹配的要求超出了这些,请考虑用Perl或Tcl写一个用户定义的函数。

Caution

使用SIMILARTO模式的搜索具有同样的安全性危险,因为SIMILARTO提供了很多和POSIX-风格正则表达式相同的能力。

9.7.1.LIKE

stringLIKEpattern[ESCAPEescape-character]stringNOTLIKEpattern[ESCAPEescape-character]如果该string匹配了提供的pattern,那么LIKE表达式返回真(和预期的一样,如果LIKE返回真,那么NOTLIKE表达式返回假,反之亦然。一个等效的表达式是NOT(stringLIKEpattern))。

如果pattern不包含百分号或者下划线,那么该模式只代表它本身的串;这时候LIKE的行为就象等号操作符。在pattern里的下划线(_)代表(匹配)任何单个字符;而一个百分号(%)匹配任何零或更多个字符的序列。

一些例子:

'abc'LIKE'abc'true'abc'LIKE'a%'true'abc'LIKE'_b_'true'abc'LIKE'c'falseLIKE模式匹配总是覆盖整个串。因此,要匹配在串内任何位置的序列,该模式必须以百分号开头和结尾。

要匹配文本的下划线或者百分号,而不是匹配其它字符,在pattern里相应的字符必须前导逃逸字符。缺省的逃逸字符是反斜线,但是你可以用ESCAPE子句指定一个不同的逃逸字符。要匹配逃逸字符本身,写两个逃逸字符。

Note:如果你关掉了standard_conforming_strings,你在文串常量中写的任何反斜线都需要被双写。

请注意反斜线在串文本里已经有特殊含义了,所以如果你写一个包含反斜线的模式常量,那你就要在SQL语句里写两个反斜线。因此,写一个匹配单个反斜线的模式实际上要在语句里写四个反斜线。你可以通过用ESCAPE选择一个不同的逃逸字符来避免这样;这样反斜线就不再是LIKE的特殊字符了。但仍然是字符文本分析器的特殊字符,所以你还是需要两个反斜线。)我们也可以通过写ESCAPE''的方式不选择逃逸字符,这样可以有效地禁用逃逸机制,但是没有办法关闭下划线和百分号在模式中的特殊含义。

关键字ILIKE可以用于替换LIKE,它令该匹配根据活动区域成为大小写无关。这个不属于SQL标准而是一个PostgreSQL扩展。

操作符等效于LIKE,而*对应ILIKE。还有!和!*操作符分别代表NOTLIKE和NOTILIKE。所有这些操作符都是PostgreSQL特有的。

9.7.2.SIMILARTO正则表达式

stringSIMILARTOpattern[ESCAPEescape-character]stringNOTSIMILARTOpattern[ESCAPEescape-character]SIMILARTO操作符根据自己的模式是否匹配给定串而返回真或者假。它和LIKE非常类似,只不过它使用SQL标准定义的正则表达式理解模式。SQL正则表达式是在LIKE标记和普通的正则表达式标记的奇怪的杂交。

类似LIKE,SIMILARTO操作符只有在它的模式匹配整个串的时候才能成功;这一点和普通的正则表达式的行为不同,在普通的正则表达式里,模式匹配串的任意部分。和LIKE类似的地方还有,SIMILARTO使用_和%作为分别代表任意单个字符和任意串的通配符(这些可以比得上POSIX正则表达式里的.和.*)。

除了这些从LIKE借用的功能之外,SIMILARTO支持下面这些从POSIX正则表达式借用的模式匹配元字符:

注意点号(.)不是SIMILARTO的一个元字符。

和LIKE一样,反斜线禁用所有这些元字符的特殊含义;当然我们也可以用ESCAPE指定一个不同的逃逸字符。

一些例子,使用#"定界返回串:

substring('foobar'from'%#"o_b#"%'for'#')oobsubstring('foobar'from'#"o_b#"%'for'#')NULL9.7.3.POSIX正则表达式

Table9-14列出了所有可用于POSIX正则表达式模式匹配的操作符。

Table9-14.正则表达式匹配操作符

POSIX正则表达式提供了比LIKE和SIMILARTO操作符更强大的含义。许多Unix工具,例如egrep、sed或awk使用一种与我们这里描述的类似的模式匹配语言。

正则表达式是一个字符序列,它是定义一个串集合(一个正则集)的缩写。如果一个串是正则表达式描述的正则集中的一员时,我们就说这个串匹配该正则表达式。和LIKE一样,模式字符准确地匹配串字符,除非在正则表达式语言里有特殊字符—不过正则表达式用的特殊字符和LIKE用的不同。和LIKE模式不一样的是,正则表达式允许匹配串里的任何位置,除非该正则表达式显式地挂接在串的开头或者结尾。

'abc'~'abc'true'abc'~'^a'true'abc'~'(b|d)'true'abc'~'^(b|c)'falsePOSIX模式语言的详细描述见下文。

带两个参数的substring函数,即substring(stringfrompattern),提供了抽取一个匹配POSIX正则表达式模式的子串的方法。如果没有匹配它返回空值,否则就是文本中匹配模式的那部分。但是如果该模式包含任何圆括号,那么将返回匹配第一对子表达式(对应第一个左圆括号的)的文本。如果你想在表达式里使用圆括号而又不想导致这个例外,那么你可以在整个表达式外边放上一对圆括号。如果你需要在想抽取的子表达式前有圆括号,参阅后文描述的非捕获性圆括号。

substring('foobar'from'o.b')oobsubstring('foobar'from'o(.)b')oregexp_replace函数提供了将匹配POSIX正则表达式模式的子串替换为新文本的功能。它的语法是regexp_replace(source,pattern,replacement[,flags])。如果没有匹配pattern,那么返回不加修改的source串。如果有匹配,则返回的source串里面的匹配子串将被replacement串替换掉。replacement串可以包含n,其中n是1到9,表明源串里匹配模式里第n个圆括号子表达式的子串应该被插入,并且它可以包含&表示应该插入匹配整个模式的子串。如果你需要放一个文字形式的反斜线在替换文本里,那么写\。flags参数是一个可选的文本串,它包含另个或更多单字母标志,这些标志可以改变函数的行为。标志i指定大小写无关的匹配,而标志g指定替换每一个匹配的子串而不仅仅是第一个。支持的标志(但不是g)在Table9-22中描述。

regexp_replace('foobarbaz','b..','X')fooXbazregexp_replace('foobarbaz','b..','X','g')fooXXregexp_replace('foobarbaz','b(..)',E'X\\1Y','g')fooXarYXazYregexp_matches函数返回一个文本数组,该数组由匹配一个POSIX正则表达式模式得到的所有被捕获子串构成。其语法是regexp_matches(string,pattern[,flags])。该函数可以不返回任何行、返回一行或者返回多行(见下文的g)。如果pattern不匹配,该函数不返回行。如果模式不包含圆括号子表达式,则每一个被返回的行都是一个单一元素的文本数组,其中包括匹配整个模式的子串。如果模式包含圆括号子表达式,该函数返回一个文本数组,它的第n个元素是匹配模式的第n个圆括号子表达式的子串("非捕获"圆括号不计算在内,详见下文)。flags参数是一个可选的文本字符串,它包含零个或更多个单字母标志,它们可以改变函数的行为。标志g让函数寻找串中的每一个匹配,而不仅仅是第一个,并且为每一个这样的匹配返回一行。支持的标志(但不是g)在Table9-22中描述。

SELECTregexp_matches('foobarbequebaz','(bar)(beque)');regexp_matches----------------{bar,beque}(1row)SELECTregexp_matches('foobarbequebazilbarfbonk','(b[^b]+)(b[^b]+)','g');regexp_matches----------------{bar,beque}{bazil,barf}(2rows)SELECTregexp_matches('foobarbequebaz','barbeque');regexp_matches----------------{barbeque}(1row)也可以强制regexp_matches()通过使用一个子选择来总是返回一行。当你希望所有行都被返回(甚至是不能匹配的行)时,把它用在一个SELECT目标列表中会特别有用:

SELECTcol1,(SELECTregexp_matches(col2,'(bar)(beque)'))FROMtab;regexp_split_to_table把一个POSIX正则表达式模式当作一个定界符来分离一个串。它的语法形式是regexp_split_to_table(string,pattern[,flags])。如果没有与pattern的匹配,该函数返回string。如果有至少有一个匹配,对每一个匹配它都返回从上一个匹配的末尾(或者串的开头)到这次匹配开头之间的文本。当没有更多匹配时,它返回从上一次匹配的末尾到串末尾之间的文本。flags参数是一个可选的文本串,它包含零个或更多单字母标志,这些标识可以改变该函数的行为。regexp_split_to_table能支持的标志在Table9-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的相同。

SELECTfooFROMregexp_split_to_table('thequickbrownfoxjumpsoverthelazydog',E'\\s+')ASfoo;foo-------thequickbrownfoxjumpsoverthelazydog(9rows)SELECTregexp_split_to_array('thequickbrownfoxjumpsoverthelazydog',E'\\s+');regexp_split_to_array-----------------------------------------------{the,quick,brown,fox,jumps,over,the,lazy,dog}(1row)SELECTfooFROMregexp_split_to_table('thequickbrownfox',E'\\s*')ASfoo;foo-----thequickbrownfox(16rows)正如上一个例子所示,正则表达式分离函数会忽略零长度的匹配,这种匹配发生在串的开头或结尾或者正好发生在前一个匹配之后。这和正则表达式匹配的严格定义是相悖的,后者由regexp_matches实现,但是通常前者是实际中最常用的行为。其他软件系统如Perl也使用相似的定义。

7.3.1.正则表达式细节

PostgreSQL的正则表达式是使用HenrySpencer写的一个包来实现的。下面的正则表达式的大部分描述都是从他的手册页中逐字拷贝过来的。

正则表达式(RE),在POSIX1003.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模式预置一个embeddedoption来选择限制更多的ERE或BRE规则,如Section9.7.3.4中所述。这对为期望准确的POSIX1003.2规则的应用提供兼容性很有用。

一个正则表达式被定义为一个或更多分支,它们之间被|分隔。只要能匹配其中一个分支的东西都能匹配正则表达式。

一个分支是一个或多个量化原子或者约束连接而成。一个原子匹配第一个,然后后面的原子匹配第二个,以此类推;一个空分支匹配空串。

一个量化原子是一个原子,后面可能跟着一个量词。没有量词的时候,它匹配一个原子,有量词的时候,它可以匹配若干个原子。一个原子可以是在Table9-15里面显示的任何可能。可能的量词和它们的含义在Table9-16里显示。

一个约束匹配一个空串,但只是在满足特定条件下才匹配。约束可以在能够使用原子的地方使用,只是它不能跟着量词。简单的约束在Table9-17里显示;更多的约束稍后描述。

Table9-15.正则表达式原子

RE不能以反斜线()结尾。

Note:如果你关掉了standard_conforming_strings,任何你写在文字串常量中的反斜线都需要被双写。

Table9-16.正则表达式量词

使用{...}的形式被称作范围。一个范围内的数字m和n都是无符号十进制整数,允许的数值从0到255(包含)。

非贪婪的量词(只在ARE中可用)匹配对应的正常(贪婪)模式,区别是它寻找最少的匹配,而不是最多的匹配。详见Section9.7.3.5。

Note:一个量词不能紧跟在另外一个量词后面,例如**是非法的。量词不能作为表达式或者子表达式的开头,也不能跟在^或者|后面。

Table9-17.正则表达式约束

ookahead和lookbehind约束不能包含后引用(参阅Section7.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中定义的一样)或者一个下划线。这是一个扩展,兼容POSIX1003.2,但那里面并没有说明,而且在准备移植到其他系统里去的软件里一定要小心使用。通常下文描述的约束逃逸更好些(它们并非更标准,但是更容易键入)。

7.3.3.正则表达式逃逸

逃逸是以开头,后面跟着一个字母数字字符得特殊序列。逃逸有好几种变体:字符项、类缩写、约束逃逸以及后引用。在ARE里,如果一个后面跟着一个字母数字,但是并未组成一个合法的逃逸,那么它是非法的。在ERE中没有逃逸:在方括号表达式之外,一个后面跟着字母数字字符的只是表示该字符是一个普通的字符,而且在一个方括号表达式里,是一个普通的字符(后者实际上在ERE和ARE不兼容)。

类缩写逃逸用来提供一些常用的字符类缩写。它们显示在Table9-19中。

约束逃逸是一个约束,如果满足特定的条件,它匹配该空串。它们显示在Table9-20中。

后引用(n)匹配数字n指定的被前面的圆括号子表达式匹配的同一个串(参阅Table9-21)。例如,([bc])1匹配bb或者cc,但是不匹配bc或者cb。RE中子表达式必须完全在后引用前面。子表达式以它们的先导圆括号的顺序编号。非捕获圆括号并不定义子表达式。

Table9-18.正则表达式字符项逃逸

十六进制位是0-9、a-f和A-F。八进制位是0-7。

指定ASCII范围(0-127)之外的值的数字字符项转义的含义取决于数据库编码。当编码是UTF-8时,转义值等价于Unicode代码点,例如u1234表示字符U+1234。对于其他多字节编码,字符项转义通常只是指定该字符的字节值的串接。如果该转义值不对应数据库编码中的任何合法字符,将不会发生错误,但是它不会匹配任何数据。

字符项逃逸总是被当作普通字符。例如,135是ASCII中的],但135并不终止一个方括号表达式。

Table9-19.正则表达式类缩写逃逸

在方括号表达式里,d、s和w会失去它们的外层方括号,而D、S和W是非法的(也就是说,例如[a-cd]等效于[a-c[:digit:]]。同样[a-cD]等效于[a-c^[:digit:]]的,也是非法的)。

Table9-20.正则表达式约束逃逸

Note:在八进制字符项逃逸和后引用之间有一个历史继承的歧义存在,这个歧义是通过下面的启发式规则解决的,像上面描述地那样。前导零总是表示这是一个八进制逃逸。而单个非零数字,如果没有跟着任何其它位,那么总是被认为后引用。一个多位的非零开头的序列也被认为是后引用,只要它出现在合适的子表达式后面(也就是说,在后引用的合法范围中的数),否则就被认为是一个八进制。

7.3.4.正则表达式元语法

除了上面描述的主要语法之外,还有几种特殊形式和杂项语法。

如果一个RE以***:开头,那么剩下的RE都被当作ARE(这在PostgreSQL中通常是无效的,因为RE被假定为ARE,但是如果ERE或BRE模式通过flags参数被指定为一个正则表达式函数时,它确实能产生效果)。如果一个RE以***=开头,那么剩下的RE被当作一个文本串,所有的字符都被认为是一个普通字符。

嵌入选项在)终止序列时发生作用。它们只在ARE的开始处起作用(在任何可能存在的***:控制器后面)。

为了这个目的,空白是空格、制表符、新行和任何属于空白字符类的字符。

最后,在ARE里,方括号表达式外面,序列(#ttt)(其中ttt是任意不包含一个))的文本)是一个注释,它被完全忽略。同样,这样的东西是不允许出现在多字符符号的字符中间的,例如(:。这种注释更像是一种历史产物而不是一种有用的设施,并且它们的使用已经被废弃;请使用扩展语法来替代。

7.3.5.正则表达式匹配规则

在RE可以在给定串中匹配多于一个子串的情况下,RE匹配串中最靠前的那个子串。如果RE可以匹配在那个位置开始的多个子串,要么是取最长的子串,要么是最短的,具体哪种,取决于RE是贪婪的还是非贪婪的。

一个RE是否贪婪取决于下面规则:

上面的规则所描述的贪婪属性不仅仅适用于独立的量化原子,而且也适用于包含量化原子的分支和整个RE。这里的意思是,匹配是按照分支或者整个RE作为一个整体匹配最长或者最短的可能子串。一旦整个匹配的长度确定,那么匹配任意特定子表达式的部分就基于该子表达式的贪婪属性进行判断,在RE里面靠前的子表达式的优先级高于靠后的子表达式。

一个相应的例子:

SELECTSUBSTRING('XY1234Z','Y*([0-9]{1,3})');结果:123SELECTSUBSTRING('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具有不同于从其元素中推导出的贪婪属性时,这很有用。例如,假设我们尝试将一个包含一些数字的字符串分隔成数字以及在它们之前和之后的部分,我们可能会尝试这样做:

SELECTregexp_matches('abc01234xyz','(.*)(\d+)(.*)');Result:{abc0123,4,xyz}这不会有用:第一个.*是贪婪的,因此它会"吃掉"尽可能多的字符而留下d+去匹配在最后一个可能位置上的最后一个数字。我们可能会通过让它变成非贪婪来修复:

SELECTregexp_matches('abc01234xyz','(.*)(\d+)(.*)');Result:{abc,0,""}这也不会有用:因为现在RE作为整体来说是非贪婪的,因此它会尽快结束全部的匹配。我们可以通过强制RE整体是贪婪的来得到我们想要的:

SELECTregexp_matches('abc01234xyz','(:(.*)(\d+)(.*)){1,1}');Result:{abc,01234,xyz}独立于RE的组件的贪婪性之外控制RE的整体贪婪性为处理变长模式提供了很大的灵活性。

在决定更长或者更短的匹配时,匹配长度是以字符衡量的,而不是排序元素。一个空串会被认为比什么都不匹配长。例如:bb*匹配abbbc的中间三个字符;(week|wee)(night|knights)匹配weeknights的所有十个字符;而(.*).*匹配abc的时候,圆括号包围的子表达式匹配所有三个字符;当(a*)*被拿来匹配bc时,整个RE和圆括号子表达式都匹配一个空串。

如果指定了新行敏感的匹配,.和使用^的方括号表达式将永远不会匹配新行字符(这样,匹配就绝对不会跨越新行,除非RE显式地安排了这样的情况)并且^和$除了分别匹配串开头和结尾之外,还将分别匹配新行后面和前面的空串。但是ARE逃逸A和Z仍然只匹配串的开头和结尾。

如果指定了部分新行敏感的匹配,那么它影响.和方括号表达式,这个时候和新行敏感的匹配一样,但是不影响^和$。

如果指定了逆新行敏感匹配,那么它影响^和$,其作用和在新行敏感的匹配里一样,但是不影响.和方括号表达式。这个并不是很有用,只是为了满足对称性而提供的。

7.3.6.限制和兼容性

在这个实现里,对RE的长度没有特别的限制。但是,那些希望高移植性的程序应该避免使用长度超过256字节的RE,因为POSIX兼容的实现可以拒绝接受这样的RE。

许多ARE扩展都是从Perl那里借来的(但是有些被做了修改来清理它们),以及一些Perl里没有出现的扩展。要注意的不兼容性包括b、B、对结尾的新行缺乏特别的处理、对那些被新行敏感匹配的东西附加的补齐方括号表达式、在lookahead/lookbehind约束里对圆括号和后引用的限制以及最长/最短匹配(而不是第一匹配)的语义。

PostgreSQL7.4之前的版本中识别的ARE和ERE语法存在两个非常明显的不兼容:

7.3.7.基本正则表达式

BRE在几个方面和ERE不太一样。在BRE中,|、+和都是普通字符并且没有与它们功能等价的东西。范围的定界符是\{和\},因为{和}本身是普通字符。嵌套的子表达式的圆括号是\(和\),因为(和)自身是普通字符。除非在RE开头或者是圆括号子表达式开头,^都是一个普通字符。除非在RE结尾或者是圆括号子表达式的结尾,$是一个普通字符。如果*出现在RE开头或者是圆括号封装的子表达式开头(前面可能有^),那么它是个普通字符。最后,可以用单数字的后引用,\<和\>分别是[[:<:]]和[[:>:]]的同义词;在BRE中没有其它可用的逃逸。8.数据类型格式化函数

Table9-23.格式化函数

Note:还有一个单一参数的to_timestamp函数,请见Table9-30。

在一个to_char输出模板串中,一些特定的模式可以被识别并且被替换成基于给定值的被恰当地格式化的数据。任何不属于模板模式的文本都简单地照字面拷贝。同样,在一个输入模板串里(对其他函数),模板模式标识由输入数据串提供的值。

虽然to_date将会拒绝混合使用格里高利和ISO周编号日期的域,to_char却不会,因为YYYY-MM-DD(IYYY-IDDD)这种输出格式也会有用。但是避免写类似IYYY-MM-DD的东西,那会得到在起始年附近令人惊讶的结果。

下面是一个更复杂的例子∶to_timestamp('15:12:02.020.001230','HH:MI:SS.MS.US')是15小时、12分钟和2秒+20毫秒+1230微秒=2.021230秒。

Table9-26展示了可以用于格式化数字值的模版模式。

Table9-26.用于数字格式化的模板模式

数字格式化的用法须知:

Table9-27.用于数字格式化的模板模式修饰语

Table9-28展示了一些使用to_char函数的例子。

Table9-28.to_char例子

所有下文描述的接受time或timestamp输入的函数和操作符实际上都有两种变体:一种接收timewithtimezone或timestampwithtimezone,另外一种接受timewithouttimezone或者timestampwithouttimezone。为了简化,这些变种没有被独立地展示。此外,+和*操作符都是可交换的操作符对(例如,date+integer和integer+date);我们只显示其中一个。

除了这些函数以外,还支持SQL操作符OVERLAPS:

SELECT(DATE'2001-02-16',DATE'2001-12-21')OVERLAPS(DATE'2001-10-30',DATE'2002-10-30');结果:trueSELECT(DATE'2001-02-16',INTERVAL'100days')OVERLAPS(DATE'2001-10-30',DATE'2002-10-30');结果:falseSELECT(DATE'2001-10-29',DATE'2001-10-30')OVERLAPS(DATE'2001-10-30',DATE'2001-10-31');结果:falseSELECT(DATE'2001-10-30',DATE'2001-10-30')OVERLAPS(DATE'2001-10-30',DATE'2001-10-31');结果:true当把一个interval值添加到timestampwithtimezone上(或从中减去)时,days部分会按照指定的天数增加或减少timestampwithtimezone的日期。对于横跨夏令时的变化(当会话的时区被设置为可识别DST的时区时),这意味着interval'1day'并不一定等于interval'24hours'。例如,当会话的时区设置为CST7CDT时,timestampwithtimezone'2005-04-0212:00-07'+interval'1day'的结果是timestampwithtimezone'2005-04-0312:00-06',而将interval'24hours'增加到相同的初始timestampwithtimezone的结果则是timestampwithtimezone'2005-04-0313:00-06',因为CST7CDT时区在2005-04-0302:00有一个夏令时变更。

注意age返回的月数域可能有歧义,因为不同的月份有不同的天数。PostgreSQL的方法是当计算部分月数时,采用两个日期中较早的月。例如:age('2004-06-01','2004-04-30')使用4月份得到1mon1day,而用5月分时会得到1mon2days,因为5月有31天,而4月只有30天。

century

世纪

SELECTEXTRACT(CENTURYFROMTIMESTAMP'2000-12-1612:21:13');结果:20SELECTEXTRACT(CENTURYFROMTIMESTAMP'2001-02-1620:38:40');结果:21第一个世纪从0001-01-0100:00:00AD开始,尽管那时候人们还不知道这是第一个世纪。这个定义适用于所有使用格里高利历法的国家。其中没有0世纪,我们直接从公元前1世纪到公元1世纪。如果你认为这个不合理,那么请把抱怨发给:罗马圣彼得教堂,梵蒂冈,教皇收。

day

对于timestamp值,是(月份)里的日域(1-31);对于interval值,是日数

SELECTEXTRACT(DAYFROMTIMESTAMP'2001-02-1620:38:40');结果:16SELECTEXTRACT(DAYFROMINTERVAL'40days1minute');结果:40decade

年份域除以10

SELECTEXTRACT(DECADEFROMTIMESTAMP'2001-02-1620:38:40');结果:200dow

一周中的日,从周日(0)到周六(6)

SELECTEXTRACT(DOWFROMTIMESTAMP'2001-02-1620:38:40');结果:5请注意,extract的一周中的日和to_char(...,'D')函数不同。

doy

一年的第几天(1-365/366)

SELECTEXTRACT(DOYFROMTIMESTAMP'2001-02-1620:38:40');结果:47epoch

SELECTto_timestamp(982384720.12);Result:2001-02-1704:38:40.12+00hour

小时域(0-23)

SELECTEXTRACT(HOURFROMTIMESTAMP'2001-02-1620:38:40');结果:20isodow

一周中的日,从周一(1)到周日(7)

SELECTEXTRACT(ISODOWFROMTIMESTAMP'2001-02-1820:38:40');结果:7除了周日,这和dow相同。这符合ISO8601中一周中的日的编号。

isoyear

日期所落在的ISO8601周编号的年(不适用于间隔)

SELECTEXTRACT(ISOYEARFROMDATE'2006-01-01');结果:2005SELECTEXTRACT(ISOYEARFROMDATE'2006-01-02');结果:2006每一个ISO8601周编号的年都开始于包含1月4日的那一周的周一,在早的1月或迟的12月中ISO年可能和格里高利年不同。更多信息见week域。

这个域不能用于PostgreSQL8.3之前的版本。

microseconds

秒域,包括小数部分,乘以1,000,000。请注意它包括全部的秒

SELECTEXTRACT(MICROSECONDSFROMTIME'17:12:28.5');结果:28500000millennium

千年

SELECTEXTRACT(MILLENNIUMFROMTIMESTAMP'2001-02-1620:38:40');结果:319xx的年份在第二个千年里。第三个千年从2001年1月1日开始。

milliseconds

秒域,包括小数部分,乘以1000。请注意它包括完整的秒。

SELECTEXTRACT(MILLISECONDSFROMTIME'17:12:28.5');结果:28500minute

分钟域(0-59)

SELECTEXTRACT(MINUTEFROMTIMESTAMP'2001-02-1620:38:40');结果:38month

对于timestamp值,它是一年里的月份数(1-12);对于interval值,它是月的数目,然后对12取模(0-11)

SELECTEXTRACT(MONTHFROMTIMESTAMP'2001-02-1620:38:40');结果:2SELECTEXTRACT(MONTHFROMINTERVAL'2years3months');结果:3SELECTEXTRACT(MONTHFROMINTERVAL'2years13months');结果:1quarter

该天所在的该年的季度(1-4)

SELECTEXTRACT(QUARTERFROMTIMESTAMP'2001-02-1620:38:40');结果:1second

秒域,包括小数部分(0-59[1])

SELECTEXTRACT(SECONDFROMTIMESTAMP'2001-02-1620:38:40');结果:40SELECTEXTRACT(SECONDFROMTIME'17:12:28.5');结果:28.5timezone

与UTC的时区偏移,以秒记。正数对应UTC东边的时区,负数对应UTC西边的时区(从技术上来看,PostgreSQL不使用UTC,因为其中不处理闰秒)。

timezone_hour时区偏移的小时部分。

timezone_minute时区偏移的分钟部分。

week

该天在所在的ISO8601周编号的年份里是第几周。根据定义,一年的第一周包含该年的1月4日并且ISO周从星期一开始。换句话说,一年的第一个星期四在第一周。

在ISO周编号系统中,早的1月的日期可能位于前一年的第五十二或者第五十三周,而迟的12月的日期可能位于下一年的第一周。例如,2005-01-01位于2004年的第五十三周,并且2006-01-01位于2005年的第五十二周,而2012-12-31位于2013年的第一周。我们推荐把isoyear域和week一起使用来得到一致的结果。

SELECTEXTRACT(WEEKFROMTIMESTAMP'2001-02-1620:38:40');结果:7year

年份域。要记住这里没有0AD,所以从AD年里抽取BC年应该小心处理。

SELECTEXTRACT(YEARFROMTIMESTAMP'2001-02-1620:38:40');结果:2001Note:当输入值为+/-Infinity时,extract对于单调增的域(epoch、julian、year、isoyear、decade、century以及millennium)返回+/-Infinity。对于其他域返回NULL。PostgreSQL9.6之前的版本对所有输入无穷的情况都返回零。

在传统的Ingres上建模的date_part函数等价于SQL标准函数extract:

date_part('field',source)请注意这里的field参数必须是一个串值,而不是一个名字。有效的date_part域名和extract相同。

SELECTdate_part('day',TIMESTAMP'2001-02-1620:38:40');结果:16SELECTdate_part('hour',INTERVAL'4hours3minutes');结果:49.2.date_trunc

date_trunc函数在概念上和用于数字的trunc函数类似。

date_trunc('field',source)source是类型timestamp或interval的值表达式(类型date和time的值都分别被自动转换成timestamp或者interval)。field选择对输入值选用什么样的精度进行截断。返回的值是timestamp类型或者所有小于选定的精度的域都设置为零(或者一,对于日期和月份)的interval。

field的有效值是∶

microsecondsmillisecondssecondminutehourdayweekmonthquarteryeardecadecenturymillennium例子:

Table9-31.ATTIMEZONEVariants

在这些表达式里,我们需要的时区zone可以指定为文本串(例如,'PST')或者一个间隔(例如,INTERVAL'-08:00')。在文本情况下,可用的时区名字可以用Section8.5.3中描述的任何方式指定。

例子(假设本地时区是PST8PDT):

函数timezone(zone,timestamp)等效于SQL兼容的结构timestampATTIMEZONEzone。

CURRENT_DATECURRENT_TIMECURRENT_TIMESTAMPCURRENT_TIME(precision)CURRENT_TIMESTAMP(precision)LOCALTIMELOCALTIMESTAMPLOCALTIME(precision)LOCALTIMESTAMP(precision)CURRENT_TIME和CURRENT_TIMESTAMP传递带有时区的值;LOCALTIME和LOCALTIMESTAMP传递的值不带时区。

CURRENT_TIME、CURRENT_TIMESTAMP、LOCALTIME和LOCALTIMESTAMP可以有选择地接受一个精度参数,该精度导致结果的秒域被园整为指定小数位。如果没有精度参数,结果将被给予所能得到的全部精度。

Note:许多其它数据库系统可能会更频繁地推进这些值。

9.5.延时执行

下面的这些函数可以用于让服务器进程延时执行:

Warning

请确保在调用pg_sleep或者其变体时,你的会话没有持有不必要的锁。否则其它会话可能必须等待你的休眠会话,因而减慢整个系统速度。

Notes

[1]如果操作系统实现了闰秒,则为60

10.枚举支持函数

对于枚举类型(在Section8.7中描述),有一些函数允许更清洁的编码,而不需要为一个枚举类型硬写特定的值。它们被列在Table9-32中。本例假定一个枚举类型被创建为:

11.几何函数和操作符

几何类型point、box、lseg、line、path、polygon和circle有一大堆本地支持函数和操作符,如Table9-33、Table9-34和Table9-35中所示。

请注意"sameas"操作符(~=),表示point、box、polygon和circle类型的一般相等概念。这些类型中的某些还有一个=操作符,但是=只比较相同的面积。其它的标量比较操作符(<=等等)也是为这些类型比较面积。

Note:在PostgreSQL之前,包含操作符@>和<@被分别称为~和@。这些名字仍然可以使用,但是已被废除并且最终将被移除。

我们可以把一个point的两个组成数字当作具有索引0和1的数组访问。例如,如果t.p是一个point列,那么SELECTp[0]FROMt检索X座标而UPDATEtSETp[1]=...改变Y座标。同样,box或者lseg类型的值可以当作两个point值的数组值看待。

函数area可以用于类型box、circle和path。area函数操作path数据类型的时候,只有在path的点没有交叉的情况下才可用。例如,path'((0,0),(0,1),(2,1),(2,2),(1,2),(1,0),(0,0))'::PATH是不行的,而下面的视觉上相同的path'((0,0),(0,1),(1,1),(1,2),(2,2),(2,1),(1,1),(1,0),(0,0))'::PATH就可以。如果交叉和不交叉的path概念让你疑惑,那么把上面两个path都画在一张图纸上,你就明白了。

12.网络地址函数和操作符

Table9-36展示了可以用于cidr和inet类型的操作符。操作符<<、<<=、>>、>>=和&&测试用于子网包含。它们只考虑两个地址的网络部分(忽略任何主机部分),然后判断其中一个网络部分是等于另外一个或者是另外一个的子网。

Table9-37展示了所有可以用于cidr和inet类型的函数。函数abbrev、host和text主要是为了提供可选的显示格式用的。

任何cidr值都能够被隐式或显式地转换为inet值,因此上述能够操作inet值的函数也同样能够操作cidr值(也有独立的用于inet和cidr的函数,因为它的行为应当和这两种情况不同)。inet值也可以转换为cidr值。完成时,该网络掩码右侧的任何位都将无声地转换为零以获得一个有效的cidr值。另外,你还可以使用常规的造型语法将一个文本字符串转换为inet或cidr值:例如,inet(expression)或colname::cidr。

macaddr类型还支持标准关系操作符(>、<=等)用于编辑次序,并且按位算术操作符(~、&和|)用于NOT、AND和OR。

13.文本搜索函数和操作符

Table9-39、Table9-40和Table9-41总结了为全文搜索提供的函数和操作符。PostgreSQL的文本搜索功能的详细解释可参考Chapter12。

Note:tsquery的包含操作符只考虑两个查询中的词位,而忽略组合操作符。

除了显示在表中的操作符,还定义了tsvector和tsquery类型的普通B-tree比较操作符(=、<等)。它们对于文本搜索不是很有用,但是允许使用。例如,建在这些类型列上的唯一索引。

Note:所有接受一个可选的regconfig参数的文本搜索函数在该参数被忽略时,使用由default_text_search_config指定的配置。

Table9-41中的函数被单独列出,因为它们通常不被用于日常的文本搜索操作。它们有助于开发和调试新的文本搜索配置。

14.XML函数

本节中描述的函数以及类函数的表达式都在类型xml的值上操作。类型xml的详细信息请参见Section8.13。用于在值和类型xml之间转换的类函数的表达式xmlparse和xmlserialize就不在这里重复介绍。使用大部分这些函数要求安装时使用了configure--with-libxml进行编译。

14.1.产生XML内容

有一组函数和类函数的表达式可以用来从SQL数据产生XML内容。它们特别适合于将查询结果格式化成XML文档以便于在客户端应用中处理。

14.1.1.xmlcomment

xmlcomment(text)

函数xmlcomment创建了一个XML值,它包含一个使用指定文本作为内容的XML注释。该文本不包含"--"或者也不会以一个"-"结尾,这样结果的结构是一个合法的XML注释。如果参数为空,结果也为空。

例子:

SELECTxmlcomment('hello');xmlcomment--------------14.1.2.xmlconcat

xmlconcat(xml[,...])

函数xmlconcat将由单个XML值组成的列表串接成一个单独的值,这个值包含一个XML内容片断。空值会被忽略,只有当没有参数为非空时结果才为空。

SELECTxmlconcat('','');xmlconcat-----------------------------------14.1.3.xmlelement

xmlelement(namename[,xmlattributes(value[ASattname][,...])][,content,...])表达式xmlelement使用给定名称、属性和内容产生一个XML元素。

SELECTxmlelement(namefoo);xmlelement------------SELECTxmlelement(namefoo,xmlattributes('xyz'asbar));xmlelement------------------SELECTxmlelement(namefoo,xmlattributes(current_dateasbar),'cont','ent');xmlelement-------------------------------------content不是合法XML名字的元素名和属性名将被逃逸,逃逸的方法是将违反的字符用序列_xHHHH_替换,其中HHHH是被替换字符的Unicode代码点的十六进制表示。例如:

SELECTxmlelement(name"foo$bar",xmlattributes('xyz'as"a&b"));xmlelement----------------------------------如果属性值是一个列引用,则不需要指定一个显式的属性名,在这种情况下列的名字将被默认用于属性的名字。在其他情况下,属性必须被给定一个显式名称。因此这个例子是合法的:

CREATETABLEtest(axml,bxml);SELECTxmlelement(nametest,xmlattributes(a,b))FROMtest;但是下面这些不合法:

SELECTxmlelement(nametest,xmlattributes('constant'),a,b)FROMtest;SELECTxmlelement(nametest,xmlattributes(func(a,b)))FROMtest;如果指定了元素内容,它们将被根据其数据类型格式化。如果内容本身也是类型xml,就可以构建复杂的XML文档。例如:

14.1.4.xmlforest

xmlforest(content[ASname][,...])

表达式xmlforest使用给定名称和内容产生一个元素的XML森林(序列)。

SELECTxmlforest('abc'ASfoo,123ASbar);xmlforest------------------------------abc123SELECTxmlforest(table_name,column_name)FROMinformation_schema.columnsWHEREtable_schema='pg_catalog';xmlforest-------------------------------------------------------------------------------------------pg_authidrolnamepg_authidrolsuper...如我们在第二个例子中所见,如果内容值是一个列引用,元素名称可以被忽略,这种情况下默认使用列名。否则,必须指定一个名字。

如上文xmlelement所示,非法XML名字的元素名会被逃逸。相似地,内容数据也会被逃逸来产生合法的XML内容,除非它已经是一个xml类型。

注意如果XML森林由多于一个元素组成,那么它不是合法的XML文档,因此在xmlelement中包装xmlforest表达式会有用处。

14.1.5.xmlpi

xmlpi(nametarget[,content])

表达式xmlpi创建一个XML处理指令。如果存在内容,内容不能包含字符序列>。

SELECTxmlpi(namephp,'echo"helloworld";');xmlpi-----------------------------14.1.6.xmlroot

xmlroot(xml,versiontext|novalue[,standaloneyes|no|novalue])

SELECTxmlroot(xmlparse(document'abc'),version'1.0',standaloneyes);xmlroot----------------------------------------abc14.1.7.xmlagg

xmlagg(xml)

和这里描述的其他函数不同,函数xmlagg是一个聚集函数。它将聚集函数调用的输入值串接起来,非常像xmlconcat所做的事情,除了串接是跨行发生的而不是在单一行的多个表达式上发生。聚集表达式的更多信息请见Section9.20。

CREATETABLEtest(yint,xxml);INSERTINTOtestVALUES(1,'abc');INSERTINTOtestVALUES(2,'');SELECTxmlagg(x)FROMtest;xmlagg----------------------abc为了决定串接的顺序,可以为聚集调用增加一个ORDERBY子句,如Section4.2.7中所述。例如:

SELECTxmlagg(xORDERBYyDESC)FROMtest;xmlagg----------------------abc我们推荐在以前的版本中使用下列非标准方法,并且它们在特定情况下仍然有用:

SELECTxmlagg(x)FROM(SELECT*FROMtestORDERBYyDESC)AStab;xmlagg----------------------abc14.2.XML谓词

这一节描述的表达式检查xml值的属性。

14.2.1.ISDOCUMENT

xmlISDOCUMENT

如果参数XML值是一个正确的XML文档,则ISDOCUMENT返回真,如果不是则返回假(即它是一个内容片断),或者是参数为空时返回空。文档和内容片断之间的区别请见Section8.13。

14.2.2.XMLEXISTS

XMLEXISTS(textPASSING[BYREF]xml[BYREF])

如果第一个参数中的XPath表达式返回任何结点,则函数xmlexists返回真,否则返回假(如果哪一个参数为空,则结果就为空)。

SELECTxmlexists('//town[text()=''Toronto'']'PASSINGBYREF'TorontoOttawa');xmlexists------------t(1row)BYREF子句在PostgreSQL中没有作用,但是为了和其他实现保持SQL一致性和兼容性还是允许它出现。每一种SQL标准,第一个BYREF是被要求的,而第二个则是可选的。也要注意SQL标准指定xmlexists结构来将一个XQuery表达式作为第一个参数,但PostgreSQL目前只支持XPath,它是XQuery的一个子集。

14.2.3.xml_is_well_formed

xml_is_well_formed(text)xml_is_well_formed_document(text)xml_is_well_formed_content(text)

这些函数检查一个text串是不是一个良构的XML,返回一个布尔结果。xml_is_well_formed_document检查一个良构的文档,而xml_is_well_formed_content检查良构的内容。如果xmloption配置参数被设置为DOCUMENT,xml_is_well_formed会做第一个函数的工作;如果配置参数被设置为CONTENT,xml_is_well_formed会做第二个函数的工作。这意味着xml_is_well_formed对于检查一个到类型xml的简单造型是否会成功非常有用,而其他两个函数对于检查XMLPARSE的对应变体是否会成功有用。

14.3.处理XML

要处理数据类型xml的值,PostgreSQL提供了函数xpath和xpath_exists,它们计算XPath1.0表达式。

xpath(xpath,xml[,nsarray])

函数xpath在XML值xml上计算XPath表达式xpath(atextvalue)。它返回一个XML值的数组,该数组对应于该XPath表达式产生的结点集合。如果该XPath表达式返回一个标量值而不是一个结点集合,将会返回一个单一元素的数组。

第二个参数必须是一个良构的XML文档。特殊地,它必须有一个单一根结点元素。

该函数可选的第三个参数是一个名字空间映射的数组。这个数组应该是一个二维text数组,其第二轴长度等于2(即它应该是一个数组的数组,其中每一个都由刚好2个元素组成)。每个数组项的第一个元素是名字空间的名称(别名),第二个元素是名字空间的URI。并不要求在这个数组中提供的别名和在XML文档本身中使用的那些名字空间相同(换句话说,在XML文档中和在xpath函数环境中,别名都是本地的)。

下面的函数将会把关系表的内容映射成XML值。它们可以被看成是XML导出功能:

table_to_xml(tblregclass,nullsboolean,tableforestboolean,targetnstext)query_to_xml(querytext,nullsboolean,tableforestboolean,targetnstext)cursor_to_xml(cursorrefcursor,countint,nullsboolean,tableforestboolean,targetnstext)每一个函数的返回值都是xml。

table_to_xml映射由参数tbl传递的命名表的内容。regclass类型接受使用常见标记标识表的字符串,包括可选的模式限定和双引号。query_to_xml执行由参数query传递的查询并且映射结果集。cursor_to_xml从cursor指定的游标中取出指定数量的行。如果需要映射一个大型的表,我们推荐这种变体,因为每一个函数都是在内存中构建结果值的。

如果tableforest为假,则结果的XML文档看起来像这样:

datadata......如果tableforest为真,结果是一个看起来像这样的XML内容片断:

datadata......如果没有表名可用,在映射一个查询或一个游标时,在第一种格式中使用串table,在第二种格式中使用row。

这几种格式的选择由用户决定。第一种格式是一个正确的XML文档,它在很多应用中都很重要。如果结果值要被重组为一个文档,第二种格式在cursor_to_xml函数中更有用。前文讨论的产生XML内容的函数(特别是xmlelement)可以被用来把结果修改成符合用户的要求。

数据值会被以前文的函数xmlelement中描述的相同方法映射。

参数nulls决定空值是否会被包含在输出中。如果为真,列中的空值被表示为:

参数targetns指定想要的结果的XML名字空间。如果没有想要的特定名字空间,将会传递一个空串。

下面的函数返回XML模式文档,这些文档描述上述对应函数所执行的映射:

table_to_xmlschema(tblregclass,nullsboolean,tableforestboolean,targetnstext)query_to_xmlschema(querytext,nullsboolean,tableforestboolean,targetnstext)cursor_to_xmlschema(cursorrefcursor,nullsboolean,tableforestboolean,targetnstext)最重要的是相同的参数被传递来获得匹配的XML数据映射和XML模式文档。

下面的函数产生XML数据映射和对应的XML模式,并把产生的结果链接在一起放在一个文档(或森林)中。在要求自包含和自描述的结果是它们非常有用:

table_to_xml_and_xmlschema(tblregclass,nullsboolean,tableforestboolean,targetnstext)query_to_xml_and_xmlschema(querytext,nullsboolean,tableforestboolean,targetnstext)另外,下面的函数可用于产生相似的整个模式或整个当前数据库的映射:

schema_to_xml(schemaname,nullsboolean,tableforestboolean,targetnstext)schema_to_xmlschema(schemaname,nullsboolean,tableforestboolean,targetnstext)schema_to_xml_and_xmlschema(schemaname,nullsboolean,tableforestboolean,targetnstext)database_to_xml(nullsboolean,tableforestboolean,targetnstext)database_to_xmlschema(nullsboolean,tableforestboolean,targetnstext)database_to_xml_and_xmlschema(nullsboolean,tableforestboolean,targetnstext)注意这些函数可能产生很多数据,它们都需要在内存中被构建。在请求大型模式或数据库的内容映射时,可以考虑分别映射每一个表,甚至通过一个游标来映射。

一个模式内容映射的结果看起来像这样:

table1-mappingtable2-mapping...其中一个表映射的格式取决于上文解释的tableforest参数。

一个数据库内容映射的结果看起来像这样:

.........其中的模式映射如上所述。

作为一个使用这些函数产生的输出的例子,Figure9-1展示了一个XSLT样式表,它将table_to_xml_and_xmlschema的输出转换为一个包含表数据的扁平转印的HTML文档。以一种相似的方式,这些函数的结果可以被转换成其他基于XML的格式。

Figure9-1.转换SQL/XML输出到HTML的XSLT样式表

Table9-42展示了可以用于两种JSON数据类型(见Section8.14)的操作符。

Table9-42.json和jsonb操作符

Note:对json和jsonb类型,这些操作符都有其并行变体。域/元素/路径抽取操作符返回与其左手输入(json或jsonb)相同的类型,不过那些被指定为返回text的除外,它们的返回值会被强制为文本。如果该JSON输入没有匹配请求的正确结构(例如那样的元素不存在),这些域/元素/路径抽取操作符会返回NULL而不是失败。接受整数JSON数组下标的域/元素/路径抽取操作符都支持表示从数组末尾开始的负值下标形式。

Table9-1中展示的标准比较操作符只对jsonb有效,而不适合json。

如Table9-43中所示,还存在一些只适合jsonb的操作符。这些操作符中的很多可以用jsonb操作符类索引。

Note:||操作符将其每一个操作数的顶层的元素串接起来。它不会递归操作。例如,如果两个操作数都是具有公共域名称的对象,结果中的域值将只是来自右手操作数的值。

Table9-44展示了可用于创建json和jsonb值的函数(没有用于jsonb的与row_to_json和array_to_json等价的函数。不过,to_jsonb函数提供了这些函数的很大一部分相同的功能)。

Note:array_to_json和row_to_json与to_json具有相同的行为,不过它们提供了更好的打印选项。针对to_json所描述的行为同样也适用于由其他JSON创建函数转换的每个值。

Note:hstore扩展有一个从hstore到json的造型,因此通过JSON创建函数转换的hstore值将被表示为JSON对象,而不是原始字符串值。

Table9-45展示了可用来处理json和jsonb值的函数。

Note:很多这些函数和操作符将把JSON字符串中的Unicode转义转换成合适的单一字符。如果输入类型是jsonb,这就没有问题,因为该转换已经完成了。但是对于json输入,这可能会导致抛出一个错误(如Section8.14所述)。

Note:在json_populate_record、json_populate_recordset、json_to_record和json_to_recordset中,来自JSON的类型强制是"尽力而为"并且对于某些类型可能得不到想要的值。JSON键会被匹配目标行类型中相同的列名。没有出现在目标行类型中的JSON域将会被从输出中忽略,并且不匹配任何JSON域的目标列将被简单地作为NULL。

Note:jsonb_set和jsonb_insert的path参数中除最后一项之外的所有项都必须存在于target中。如果create_missing为假,jsonb_set的path参数的所有项都必须存在。如果这些条件不满足,则返回的target不会被改变。

如果最后的路径项是一个对象键,在它不存在且给定了新值的情况下会创建它。如果最后的路径项是一个数组索引,为正值则表示从左边开始计数,为负值表示从右边开始计数--1表示最右边的元素,以此类推。如果该项超过范围-array_length..array_length-1并且create_missing为真,则该项为负时把新值加载数组的开始处,而该项为正时把新值加在数组的末尾处。

Note:不要把json_typeof函数的null返回值与SQL的NULL弄混。虽然调用json_typeof('null'::json)将会返回null,但调用json_typeof(NULL::json)将会返回一个SQL的NULL。

Note:如果json_strip_nulls的参数在任何对象中包含重复的域名称,结果在语义上可能有所不同,具体取决于它们发生的顺序。这不是jsonb_strip_nulls的一个问题,因为jsonb值不能具有重复的对象域名称。

16.序列操作函数

本节描述用于操作序列对象的函数,序列对象也被称为序列生成器或者就是序列。序列对象都是用CREATESEQUENCE创建的特殊的单行表。序列对象通常用于为表的行生成唯一的标识符。Table9-46中列出的这些序列函数,可以为我们从序列对象中获取连续的序列值提供了简单的、多用户安全的方法。

Table9-46.序列函数

nextval('foo')操作序列foonextval('FOO')操作序列foonextval('"Foo"')操作序列Foo必要时序列名可以用模式限定∶

nextval('myschema.foo')操作myschema.foonextval('"myschema".foo')同上nextval('foo')在搜索路径中查找fooNote:在PostgreSQL8.1之前,序列函数的参数类型是text,而不是regclass,并且前文所述的从文本串到OID值的转换将在每次调用的时候发生。为了向后兼容,这个处理仍然存在,但是在内部实际上是通过在函数调用前隐式地将text转换成regclass实现的。

当你把一个序列函数的参数写成一个无修饰的文字串,那么它将变成类型为regclass的常量。因为这只是一个OID,它将跟踪最初标识的序列,而不管后面是否改名、模式变化等等。这种"早期绑定"的行为通常是列默认值和视图中引用的序列所需要的。但是有时候你可能想要"延迟绑定",其中序列的引用是在运行时解析的。要得到延迟绑定的行为,我们可以强制常量被存储为text常量,而不是regclass:

nextval('foo'::text)foo在运行时查找请注意,延迟绑定是PostgreSQL版本8.1之前唯一被支持的行为,因此你可能需要做这些来保留旧应用的语义。

当然,序列函数的参数也可以是表达式。如果它是一个文本表达式,那么隐式的转换将导致运行时的查找。

可用的序列函数有∶

nextval

递增序列对象到它的下一个值并且返回该值。这个动作是自动完成的:即使多个会话并发执行nextval,每个进程也会安全地收到一个唯一的序列值。

如果一个序列对象是用默认参数创建的,连续的nextval调用将会返回从1开始的连续的值。其他的行为可以通过在CREATESEQUENCE命令中使用特殊参数来获得;详见该命令的参考页。

Important:为了避免阻塞从同一个序列获取序号的并发事务,nextval操作从来不会被回滚。也就是说,一旦一个值被取出就视同被用掉并且不会被再次返回给调用者,即便调用该操作的外层事务后来中止或者调用查询后来没有使用取得的值也是这样。例如一个带有ONCONFLICT子句的INSERT会计算要被插入的元组,其中可能就包括调用nextval,然后才会检测到导致它转向ONCONFLICT规则的冲突。这种情况就会在已分配值的序列中留下未被使用的"空洞"。因此,PostgreSQL的序列对象不能被用来得到"无间隙"的序列。

currval

在当前会话中返回最近一次nextval取到的该序列的值(如果在本会话中从未在该序列上调用过nextval,那么会报告一个错误)。请注意因为此函数返回一个会话本地的值,不论其它会话是否在当前会话之后执行过nextval,它都能给出一个可预测的回答。

lastval

返回当前会话里最近一次nextval返回的值。这个函数等效于currval,只是它不用序列名作为参数,它会引用当前会话里面最近一次被应用的序列的nextval。如果当前会话还没有调用过nextval,那么调用lastval会报错。

setval

重置序列对象的计数器值。双参数的形式设置序列的last_value域为指定值并且将其is_called域设置为true,表示下一次nextval将在返回值之前递增该序列。currval报告的值也被设置为指定的值。在三参数形式里,is_called可以设置为true或false。true具有和双参数形式相同的效果。如果你把它设置为false,那么下一次nextval将返回指定的值,而从随后的nextval才开始递增该序列。此外,在这种情况中currval报告的值不会被改变。例如:

SELECTsetval('foo',42);下一次nextval会返回43SELECTsetval('foo',42,true);同上SELECTsetval('foo',42,false);下一次nextval将返回42setval返回的结果就是它的第二个参数的值。

Important:因为序列是非事务的,setval造成的改变不会由于事务的回滚而撤销。

17.条件表达式

本节描述在PostgreSQL中可用的SQL兼容的条件表达式。

Tip:如果你的需求超过这些条件表达式的能力,你可能会希望用一种更富表现力的编程语言写一个存储过程。

17.1.CASE

SQLCASE表达式是一种通用的条件表达式,类似于其它编程语言中的if/else语句:

CASEWHENconditionTHENresult[WHEN...][ELSEresult]ENDCASE子句可以用于任何表达式可以出现的地方。每一个condition是一个返回boolean结果的表达式。如果结果为真,那么CASE表达式的结果就是符合条件的result,并且剩下的CASE表达式不会被处理。如果条件的结果不为真,那么以相同方式搜寻任何随后的WHEN子句。如果没有WHENcondition为真,那么CASE表达式的值就是在ELSE子句里的result。如果省略了ELSE子句而且没有条件为真,结果为空。

SELECT*FROMtest;a---123SELECTa,CASEWHENa=1THEN'one'WHENa=2THEN'two'ELSE'other'ENDFROMtest;a|case---+-------1|one2|two3|other所有result表达式的数据类型都必须可以转换成单一的输出类型。参阅Section10.5获取细节。

下面这个"简单"形式的CASE表达式是上述通用形式的一个变种:

CASEexpressionWHENvalueTHENresult[WHEN...][ELSEresult]END第一个expression会被计算,然后与所有在WHEN子句中的每一个value对比,直到找到一个相等的。如果没有找到匹配的,则返回在ELSE子句中的result(或者控制)。这类似于C里的switch语句。

上面的例子可以用简单CASE语法来写:

SELECTa,CASEaWHEN1THEN'one'WHEN2THEN'two'ELSE'other'ENDFROMtest;a|case---+-------1|one2|two3|otherCASE表达式并不计算任何无助于判断结果的子表达式。例如,下面是一个可以避免被零除错误的方法:

SELECT...WHERECASEWHENx<>0THENy/x>1.5ELSEfalseEND;Note:如Section4.2.14中所述,在有几种情况中一个表达式的子表达式会被计算多次,因此"CASE只计算必要的表达式"这一原则并非不可打破。例如一个常量子表达式1/0通常将会在规划时导致一次除零错误,即便它位于一个执行时永远也不会进入的CASE分支时也是如此。

17.2.COALESCE

COALESCE(value[,...])

COALESCE函数返回它的第一个非空参数的值。当且仅当所有参数都为空时才会返回空。它常用于在为显示目的检索数据时用缺省值替换空值。例如:

SELECTCOALESCE(description,short_description,'(none)')...如果description不为空,这将会返回它的值,否则如果short_description非空则返回short_description的值,如果前两个都为空则返回(none)。

和CASE表达式一样,COALESCE将不会计算无助于判断结果的参数;也就是说,在第一个非空参数右边的参数不会被计算。这个SQL标准函数提供了类似于NVL和IFNULL的能力,它们被用在某些其他数据库系统中。

17.3.NULLIF

NULLIF(value1,value2)

当value1和value2相等时,NULLIF返回一个空值。否则它返回value1。这些可以用于执行前文给出的COALESCE例子的逆操作:

SELECTNULLIF(value,'(none)')...在这个例子中,如果value是(none),将返回空值,否则返回value的值。

17.4.GREATEST和LEAST

GREATEST(value[,...])LEAST(value[,...])GREATEST和LEAST函数从一个任意的数字表达式列表里选取最大或者最小的数值。这些表达式必须都可以转换成一个普通的数据类型,它将会是结果类型(参阅Section10.5获取细节)。列表中的NULL数值将被忽略。只有所有表达式的结果都是NULL的时候,结果才会是NULL。

请注意GREATEST和LEAST都不是SQL标准,但却是很常见的扩展。某些其他数据库让它们在任何参数为NULL时返回NULL,而不是在所有参数都为NULL时才返回NULL。

18.数组函数和操作符

Table9-47显示了可以用于数组类型的操作符。

数组比较使用默认的B-Tree在元素数据类型上的比较函数对数组内容按元素逐一进行。多维数组的元素按照行序进行访问(最后的下标变化最快)。如果两个数组的内容相同但维数不等,那么维度信息中的第一个不同将决定排序顺序(这是对PostgreSQL8.2之前版本的修改:老版本认为内容相同的两个数组相等,即使它们的维数或下标范围并不相同)。

Table9-48展示了可以用于数组类型的函数。

在array_position和array_positions中,每一个数组元素都使用ISNOTDISTINCTFROM语义与要搜索的值比较。

在array_position中,如果值没有找到则返回NULL。

在array_positions中,只有当数组为NULL时才返回NULL,如果该值没有在该数组中找到则返回一个空数组。

在string_to_array中,如果定界符参数为NULL,输入字符串中的每一个字符将变成结果数组中的一个独立元素。如果定界符是一个空串,则整个输入字符串被作为一个单一元素的数组返回。否则输入字符串会被在每一个出现定界符字符串的位置分裂。

在string_to_array中,如果空值串参数被忽略或者为NULL,输入中的子串不会被替换成NULL。在array_to_string中,如果空值串参数被忽略或者为NULL,该数组中的任何空值元素会被简单地跳过并且不会在输出串中被表示。

Note:string_to_array的行为中有两点与PostgreSQL9.1之前的版本不同。首先,当输入串的长度为零时,它将返回一个空(无元素)数组而不是NULL。其次,如果定界符串为NULL,该函数会将输入划分成独立字符,而不是像以前那样返回NULL。

19.范围函数和操作符

范围类型的概述请见Section8.17。

Table9-49展示了范围类型可用的操作符。

简单比较操作符<、>、<=和>=首先比较下界,并且只有在下界相等时才比较上界。这些比较通常对范围不怎么有用,但是还是提供它们以便能够在范围上构建B树索引。

当涉及一个空范围时,左部/右部/相邻操作符总是返回假;即一个空范围被认为不在任何其他范围前面或者后面。

如果结果范围可能需要包含两个分离的子范围,并和差操作符将会失败,因为这样的范围无法被表示。

Table9-50显示可用于范围类型的函数。

如果范围为空或者被请求的界是无限的,lower和upper函数返回空值。函数lower_inc、upper_inc、lower_inf和upper_inf对一个空范围全部返回假。

20.聚集函数

请注意,除了count以外,这些函数在没有行被选中时返回控制。尤其是sum函数在没有输入行时返回空值,而不是零,并且array_agg在这种情况返回空值而不是一个空数组。必要时可以用coalesce把空值替换成零或一个空数组。

支持部分模式的聚集函数有资格参与到各种优化中,例如并行聚集。

Note:布尔聚集bool_and和bool_or对应于标准的SQL聚集every和any或some。而对于any和some,似乎在标准语法中有一个歧义:

SELECTb1=ANY((SELECTb2FROMt2...))FROMt1...;如果子查询返回一行有一个布尔值的结果,这里的ANY可以被认为是引入一个子查询,或者是作为一个聚集函数。因而标准的名称不能指定给这些聚集。

Note:在把count聚集应用到整个表上时,习惯于使用其他SQL数据管理系统的用户可能会对它的性能感到失望。一个如下的查询:

SELECTcount(*)FROMsometable;将会要求与整个表大小成比例的工作:PostgreSQL将需要扫描整个表或者整个包含表中所有行的索引。

与相似的用户定义的聚集函数一样,聚集函数array_agg、json_agg、jsonb_agg、json_object_agg、jsonb_object_agg、string_agg和xmlagg会依赖输入值的顺序产生有意义的不同结果值。这个顺序默认是不用指定的,但是可以在聚集调用时使用ORDERBY子句进行控制,如Section4.2.7中所示。作为一种选择,从一个排序号的子查询来提供输入值通常会有帮助。例如:

SELECTxmlagg(x)FROM(SELECTxFROMtestORDERBYyDESC)AStab;注意如果外面的查询层次包含额外的处理(例如连接),这种方法可能会失败,因为这可能导致子查询的输出在计算聚集之前被重新排序。

Table9-52展示了通常被用在统计分析中的聚集函数(这些被隔离出来是为了不和常用聚集混淆)。其中描述提到了N,它表示对应于所有非空输入表达式的输入行的数目。在所有情况中,如果计算是无意义的,将会返回空值,例如当N为零。

Table9-52.用于统计的聚集函数

Table9-53展示了一些使用有序集聚集语法的聚集函数。这些函数有时也被称为"逆分布"函数。

Table9-53.有序集聚集函数

所有列在Table9-53中的聚集会忽略它们的已排序输入中的空值。对那些有一个fraction参数的聚集来说,该分数值必须位于0和1之间,否则会抛出错误。不过,一个空分数值会产生一个空结果。

对于这些假想集聚集的每一个,args中给定的直接参数列表必须匹配sorted_args中给定的聚集参数的数量和类型。与大部分的内建聚集不同,这些聚集并不严格,即它们不会丢弃包含空值的输入行。空值的排序根据ORDERBY子句中指定的规则进行。

=>SELECT*FROMitems_sold;make|model|sales-------+-------+-------Foo|GT|10Foo|Tour|20Bar|City|15Bar|Sport|5(4rows)=>SELECTmake,model,GROUPING(make,model),sum(sales)FROMitems_soldGROUPBYROLLUP(make,model);make|model|grouping|sum-------+-------+----------+-----Foo|GT|0|10Foo|Tour|0|20Bar|City|0|15Bar|Sport|0|5Foo||1|30Bar||1|20||3|50(7rows)Table9-56列出了内建的窗口函数。注意必须使用窗口函数的语法调用这些函数;一个OVER子句是必需的。

除了这些函数外,任何内建的或用户定义的普通聚集函数(但有序集或假想集聚集除外)都可以作为窗口函数。仅当调用跟着OVER子句时,聚集函数才会作为窗口函数;否则它们作为常规的聚集。

Table9-56.通用窗口函数

Note:SQL标准为lead、lag、first_value、last_value和nth_value定义了一个RESPECTNULLS或IGNORENULLS选项。这在PostgreSQL中没有实现:行为总是与标准的默认相同,即RESPECTNULLS。同样,标准中用于nth_value的FROMFIRST或FROMLAST选项没有实现:只有支持默认的FROMFIRST行为(你可以通过反转ORDERBY的排序达到FROMLAST的结果)。

22.子查询表达式

本节描述PostgreSQL中可用的SQL兼容的子查询表达式。所有本节中成文的表达式都返回布尔值(真/假)结果。

22.1.EXISTS

EXISTS(subquery)

EXISTS的参数是一个任意的SELECT语句,或者说子查询。系统对子查询进行运算以判断它是否返回行。如果它至少返回一行,那么EXISTS的结果就为"真";如果子查询没有返回行,那么EXISTS的结果是"假"。

子查询可以引用来自周围的查询的变量,这些变量在该子查询的任何一次计算中都起常量的作用。

这个子查询通常只是运行到能判断它是否可以返回至少一行为止,而不是等到全部结束。在这里写任何有副作用的子查询都是不明智的(例如调用序列函数);这些副作用是否发生是很难判断的。

因为结果只取决于是否会返回行,而不取决于这些行的内容,所以这个子查询的输出列表通常是无关紧要的。一个常用的编码习惯是用EXISTS(SELECT1WHERE...)的形式写所有的EXISTS测试。不过这条规则有例外,例如那些使用INTERSECT的子查询。

下面这个简单的例子类似在col2上的一次内联接,但是它为每个tab1的行生成最多一个输出,即使存在多个匹配tab2的行也如此∶

SELECTcol1FROMtab1WHEREEXISTS(SELECT1FROMtab2WHEREcol2=tab1.col2);22.2.IN

expressionIN(subquery)

右手边是一个圆括弧括起来的子查询,它必须正好只返回一个列。左手边表达式将被计算并与子查询结果逐行进行比较。如果找到任何等于子查询行的情况,那么IN的结果就是"真"。如果没有找到相等行,那么结果是"假"(包括子查询没有返回任何行的情况)。

请注意如果左手边表达式得到空值,或者没有相等的右手边值,并且至少有一个右手边行得到空值,那么IN结构的结果将是空值,而不是假。这个行为是遵照SQL处理空值的一般规则的。

和EXISTS一样,假设子查询将被完成运行完全是不明智的。

row_constructorIN(subquery)

这种形式的IN的左手边是一个行构造器,如Section4.2.13中所述。右手边是一个圆括弧子查询,它必须返回和左手边返回的行中表达式所构成的完全一样多的列。左手边表达式将被计算并与子查询结果逐行进行比较。如果找到任意相等的子查询行,则IN的结果为"true"。如果没有找到相等行,那么结果为"假"(包括子查询不返回行的情况)。

通常,表达式或者子查询行里的空值是按照SQL布尔表达式的一般规则进行组合的。如果两个行对应的成员都非空并且相等,那么认为这两行相等;如果任意对应成员为非空且不等,那么这两行不等;否则这样的行比较的结果是未知(空值)。如果所有行的结果要么是不等,要么是空值,并且至少有一个空值,那么IN的结果是空值。

22.3.NOTIN

expressionNOTIN(subquery)

右手边是一个用圆括弧包围的子查询,它必须返回正好一个列。左手边表达式将被计算并与子查询结果逐行进行比较。如果只找到不相等的子查询行(包括子查询不返回行的情况),那么NOTIN的结果是"真"。如果找到任何相等行,则结果为"假"。

请注意如果左手边表达式得到空值,或者没有相等的右手边值,并且至少有一个右手边行得到空值,那么NOTIN结构的结果将是空值,而不是真。这个行为是遵照SQL处理空值的一般规则的。

和EXISTS一样,假设子查询会完全结束是不明智的。

row_constructorNOTIN(subquery)

这种形式的NOTIN的左手边是一个行构造器,如Section4.2.13中所述。右手边是一个圆括弧子查询,它必须返回和左手边返回的行中表达式所构成的完全一样多的列。左手边表达式将被计算并与子查询结果逐行进行比较。如果找到不等于子查询行的行,则NOTIN的结果为"true"。如果找到相等行,那么结果为"假"(包括子查询不返回行的情况)。

通常,表达式或者子查询行里的空值是按照SQL布尔表达式的一般规则进行组合的。如果两个行对应的成员都非空并且相等,那么认为这两行相等;如果任意对应成员为非空且不等,那么这两行不等;否则这样的行比较的结果是未知(空值)。如果所有行的结果要么是不等,要么是空值,并且至少有一个空值,那么NOTIN的结果是空值。

22.4.ANY/SOME

expressionoperatorANY(subquery)expressionoperatorSOME(subquery)

这种形式的右手边是一个圆括弧括起来的子查询,它必须返回正好一个列。左手边表达式将被计算并使用给出的操作符对子查询结果逐行进行比较。如果获得任何真值结果,那么ANY的结果就是"真"。如果没有找到真值结果,那么结果是"假"(包括子查询没有返回任何行的情况)。

SOME是ANY的同义词。IN等价于=ANY。

请注意如果没有任何成功并且至少有一个右手边行为该操作符结果生成空值,那么ANY结构的结果将是空值,而不是假。这个行为是遵照SQL处理空值布尔组合的一般规则制定的。

和EXISTS一样,假设子查询将被完全运行是不明智的。

row_constructoroperatorANY(subquery)row_constructoroperatorSOME(subquery)

这种形式的左手边是一个行构造器,如Section4.2.13所述。右手边是一个圆括弧括起来的子查询,它必须返回和左手边列表给出的表达式一样多的列。左手边表达式将被计算并使用给出的操作符对子查询结果逐行进行比较。如果比较为任何子查询行返回真,则ANY的结果为"真"。如果比较对每一个子查询行都返回假,则结果为"假"(包括子查询不返回行的情况)。如果比较不对任何行返回真并且至少对一行返回NULL,则结果为NULL。

22.5.ALL

expressionoperatorALL(subquery)ALL的这种形式的右手边是一个圆括弧括起来的子查询,它必须只返回一列。左手边表达式将被计算并使用给出的操作符对子查询结果逐行进行比较。该操作符必须生成布尔结果。如果所有行得到真(包括子查询没有返回任何行的情况),ALL的结果就是"真"。如果没有存在任何假值结果,那么结果是"假"。如果比较为任何行都不返回假并且对至少一行返回NULL,则结果为NULL。

NOTIN等价于<>ALL。

row_constructoroperatorALL(subquery)

ALL的这种形式的左手边是一个行构造器,右手边是一个圆括弧括起来的子查询,它必须返回和左手边行中表达式一样多的列。左手边表达式将被计算并使用给出的操作符对子查询结果逐行进行比较。如果对所有子查询行该比较都返回真,那么ALL的结果就是"真"(包括子查询没有返回任何行的情况)。如果对任何子查询行比较返回假,则结果为"假"。如果比较对任何子查询行都不返回假并且对至少一行返回NULL,则结果为NULL。

22.6.单一行比较

row_constructoroperator(subquery)

左手边是一个行构造器,右手边是一个圆括弧括起来的子查询,该查询必须返回和左手边行中表达式数目完全一样的列。另外,该子查询不能返回超过一行的数量(如果它返回零行,那么结果就是空值)。左手边被计算并逐行与右手边的子查询结果行比较。

23.行和数组比较

23.1.IN

expressionIN(value[,...])右手边是一个圆括弧包围的标量列表。如果左手边表达式的结果等于任何右手边表达式中的一个,结果为"真"。它是下面形式的缩写

expression=value1ORexpression=value2OR...请注意如果左手边表达式得到空值,或者没有相等的右手边值并且至少有一个右手边的表达式得到空值,那么IN结构的结果将为空值,而不是假。这符合SQL处理空值的布尔组合的一般规则。

23.2.NOTIN

expressionNOTIN(value[,...])右手边是一个圆括弧包围的标量列表。如果左手边表达式的结果不等于所有右手边表达式,结果为"真"。它是下面形式的缩写

expression<>value1ANDexpression<>value2AND...请注意如果左手边表达式得到空值,或者没有相等的右手边值并且至少有一个右手边的表达式得到空值,那么NOTIN结构的结果将为空值,而不是我们可能天真地认为的真值。这符合SQL处理空值的布尔组合的一般规则。

Tip:xNOTINy在所有情况下都等效于NOT(xINy)。但是,在处理空值的时候,用NOTIN比用IN更可能迷惑新手。最好尽可能用正逻辑来表达你的条件。

23.3.ANY/SOME(array)

expressionoperatorANY(arrayexpression)expressionoperatorSOME(arrayexpression)

右手边是一个圆括弧包围的表达式,它必须得到一个数组值。左手边表达式被计算并且使用给出的操作符对数组的每个元素进行比较,这个操作符必须得到布尔结果。如果得到了任何真值结果,那么ANY的结果是"真"。如果没有找到真值结果(包括数组只有零个元素的情况),那么结果是"假"。

如果数组表达式得到一个空数组,ANY的结果将为空值。如果左手边的表达式得到空值,ANY通常是空值(尽管一个非严格比较操作符可能得到一个不同的结果)。另外,如果右手边的数组包含任何空值元素或者没有得到真值比较结果,ANY的结果将是空值而不是假(再次,假设是一个严格的比较操作符)。这符合SQL对空值的布尔组合的一般规则。

SOME是ANY的同义词。

23.4.ALL(array)

expressionoperatorALL(arrayexpression)

右手边是一个圆括弧包围的表达式,它必须得到一个数组值。左手边表达式将被计算并使用给出的操作符与数组的每个元素进行比较,这个操作符必须得到一个布尔结果。如果所有比较都得到真值结果,那么ALL的结果是"真"(包括数组只有零个元素的情况)。如果有任何假值结果,那么结果是"假"。

如果数组表达式得到一个空数组,ALL的结果将为空值。如果左手边的表达式得到空值,ALL通常是空值(尽管一个非严格比较操作符可能得到一个不同的结果)。另外,如果右手边的数组包含任何空值元素或者没有得到假值比较结果,ALL的结果将是空值而不是真(再次,假设是一个严格的比较操作符)。这符合SQL对空值的布尔组合的一般规则。

23.5.行构造器比较

row_constructoroperatorrow_constructor

每一边都是一个行构造器,如Section4.2.13所述。两个行值必须具有相同数量的域。每一边被计算并且被逐行比较。当操作符是=、<>、<<=、>、>=时,允许进行行构造器比较。每一个行元素必须是具有一个默认B树操作符类的类型,否则尝试比较会产生一个错误。

Note:Errorsrelatedtothenumberortypesofelementsmightnotoccurifthecomparisonisresolvedusingearliercolumns.

=和<>情况略有不同。如果两行的所有对应成员都是非空且相等则这两行被认为相等;如果任何对应成员是非空但是不相等则这两行不相等;否则行比较的结果为未知(空值)。

对于<、<=、>和>=情况,行元素被从左至右比较,在找到一处不等的或为空的元素对就立刻停下来。如果这一对元素都为空值,则行比较的结果为未知(空值);否则这一对元素的比较结果决定行比较的结果。例如,ROW(1,2,NULL)

row_constructorISDISTINCTFROMrow_constructor

这个结构与<>行比较相似,但是它对于空值输入不会得到空值。任何空值被认为和任何非空值不相等(有区别),并且任意两个空值被认为相等(无区别)。因此结果将总是为真或为假,永远不会是空值。

row_constructorISNOTDISTINCTFROMrow_constructor

这个结构与=行比较相似,但是它对于空值输入不会得到空值。任何空值被认为和任何非空值不相等(有区别),并且任意两个空值被认为相等(无区别)。因此结果将总是为真或为假,永远不会是空值。

23.6.组合类型比较

recordoperatorrecordSQL规范要求在结果依赖于比较两个NULL值或者一个NULL与一个非NULL时逐行比较返回NULL。PostgreSQL只有在比较两个行构造器(如Section9.23.5)的结果或者比较一个行构造器与一个子查询的输出时才这样做(如Section9.22中所述)。在其他比较两个组合类型值的环境中,两个NULL域值被认为相等,并且一个NULL被认为大于一个非NULL。为了得到组合类型的一致的排序和索引行为,这样做是必要的。

每一边都会被计算并且它们会被逐行比较。当操作符是=、<>、<、<=、>或者>=时或者具有与这些类似的语义时,允许组合类型的比较(更准确地说,如果一个操作符是一个B树操作符类的成员,或者是一个B树操作符类的=成员的否定词,它就可以是一个行比较操作符)。上述操作符的行为与用于行构造器(见Section9.23.5)的IS[NOT]DISTINCTFROM相同。

为了支持包含无默认B树操作符类的元素的行匹配,为组合类型比较定义了下列操作符:=,<>,<,<=,>,and>=.这些操作符比较两行的内部二进制表达。即使两行用相等操作符的比较为真,两行也可能具有不同的二进制表达。行在这些比较操作符之下的排序是决定性的,其他倒没什么意义。这些操作符在内部被用于物化视图并且可能对其他如复制之类的特殊功能有用,但是它们并不打算用在书写查询这类普通用途中。

24.集合返回函数

本节描述那些可能返回多于一行的函数。目前这个类中被使用最广泛的是级数生成函数,如Table9-57和Table9-58所述。其他更特殊的集合返回函数在本手册的其他地方描述。

Table9-57.级数生成函数

当step为正时,如果start大于stop则返回零行。相反,当step为负时,如果start小于stop则返回零行。对于NULL输入也会返回零行。step为零是一个错误。下面是一些例子:

SELECT*FROMgenerate_series(2,4);generate_series-----------------234(3rows)SELECT*FROMgenerate_series(5,1,-2);generate_series-----------------531(3rows)SELECT*FROMgenerate_series(4,3);generate_series-----------------(0rows)SELECTgenerate_series(1.1,4,1.3);generate_series-----------------1.12.43.7(3rows)--这个例子依赖于日期+整数操作符SELECTcurrent_date+s.aASdatesFROMgenerate_series(0,14,7)ASs(a);dates------------2004-02-052004-02-122004-02-19(3rows)SELECT*FROMgenerate_series('2008-03-0100:00'::timestamp,'2008-03-0412:00','10hours');generate_series---------------------2008-03-0100:00:002008-03-0110:00:002008-03-0120:00:002008-03-0206:00:002008-03-0216:00:002008-03-0302:00:002008-03-0312:00:002008-03-0322:00:002008-03-0408:00:00(9rows)Table9-58.下标生成函数

generate_subscripts是一个快捷函数,它为给定数组的指定维度生成一组合法的下标。对于不具有请求维度的数组返回零行,对于NULL数组也返回零行(但是会对NULL数组元素返回合法的下标)。下面是一些例子:

Table9-59展示了多个可以抽取会话和系统信息的函数。

Table9-59.会话信息函数

Note:current_catalog、current_schema、current_user、session_user和user在SQL里有特殊的语意状态:它们被调用时结尾不要跟着园括号(在PostgreSQL中,圆括号可以有选择性地被用于current_schema,但是不能和其他的一起用)。

session_user通常是发起当前数据库连接的用户,不过超级用户可以用SETSESSIONAUTHORIZATION修改这个设置。current_user是用于权限检查的用户标识。通常,它总是等于会话用户,但是可以被SETROLE改变。它也会在函数执行的过程中随着属性SECURITYDEFINER的改变而改变。在Unix的说法里,那么会话用户是"真实用户",而当前用户是"有效用户"。

Note:搜索路径可以在运行时修改。命令是:

SETsearch_pathTOschema[,schema,...]inet_client_addr返回当前客户端的IP地址,inet_client_port返回它的端口号。inet_server_addr返回接受当前连接的服务器的IP地址,而inet_server_port返回对应的端口号。如果连接是通过Unix域套接字进行的,那么所有这些函数都返回NULL。

pg_my_temp_schema返回当前会话临时模式的OID,如果没有使用临时模式(因为它没有创建任何临时表)则返回零。如果给定的OID是另一个会话的临时模式的OID,则pg_is_other_temp_schema返回真(这是有用的,例如,要将其他会话的临时表从一个目录显示中排除)。

pg_listening_channels返回当前会话正在监听的异步通知频道的名称的集合。pg_notification_queue_usage返回等待处理的通知占可用的通知空间的比例,它是一个0-1范围内的double值。详见LISTEN和NOTIFY。

pg_postmaster_start_time返回服务器启动的timestampwithtimezone。

version返回一个描述PostgreSQL服务器版本的字符串。你也可以从server_version或者一个机器可读的版本server_version_num得到这个信息。软件开发者应该使用server_version_num(从8.2开始可用)或者PQserverVersion,而不必解析文本形式的版本。

Table9-60列出那些允许用户编程查询对象访问权限的函数。参阅Section5.6获取更多有关权限的信息。

Table9-60.访问权限查询函数

has_table_privilege判断一个用户是否可以用某种特定的方式访问一个表。该用户可以通过名字或者OID(pg_authid.oid)来指定,也可以用public表示PUBLIC伪角色。如果省略该参数,则使用current_user。该表可以通过名字或者OID指定(因此,实际上有六种has_table_privilege的变体,我们可以通过它们的参数数目和类型来区分它们)。如果用名字指定,那么在必要时该名字可以是模式限定的。所希望的权限类型是用一个文本串来指定的,它必须是下面的几个值之一:SELECT、INSERT、UPDATE、DELETE、TRUNCATE、REFERENCES或TRIGGER。WITHGRANTOPTION可以被选择增加到一个权限类型来测试是否该权限是使用转授选项得到。另外,可以使用逗号分隔来列出多个权限类型,在这种情况下只要具有其中之一的权限则结果为真(权限字符串的大小写并不重要,可以在权限名称之间出现额外的空白,但是在权限名内部不能有空白)。一些例子:

SELECThas_table_privilege('myschema.mytable','select');SELECThas_table_privilege('joe','mytable','INSERT,SELECTWITHGRANTOPTION');has_sequence_privilege检查一个用户是否能以某种特定方式访问一个序列。它的参数可能性和has_table_privilege相似。所希望测试的访问权限类型必须是下列之一:USAGE、SELECT或UPDATE。

has_column_privilege检查一个用户是否能以特定方式访问一个列。它的参数可能性与has_table_privilege类似,并且列还可以使用名字或者属性号来指定。希望的访问权限类型必须是下列值的某种组合:SELECT、INSERT、UPDATE或REFERENCES。注意在表级别上具有这些权限中的任意一种将会隐式地把它授予给表上的每一列。

has_database_privilege检查一个用户是否能以特定方式访问一个数据库。它的参数可能性类似has_table_privilege。希望的访问权限类型必须是以下值的某种组合:CREATE、CONNECT、TEMPORARY或TEMP(等价于TEMPORARY)。

has_function_privilege检查一个用户是否能以特定方式访问一个函数。其参数可能性类似has_table_privilege。在用一个文本串而不是OID指定一个函数时,允许的输入和regprocedure数据类型一样(参阅Section8.18)。希望的访问权限类型必须是EXECUTE。一个例子:

SELECThas_function_privilege('joeuser','myfunc(int,text)','execute');has_foreign_data_wrapper_privilege检查一个用户是否能以特定方式访问一个外部数据包装器。它的参数可能性类似于has_table_privilege。希望的访问权限类型必须是USAGE。

has_language_privilege检查一个用户是否可以以某种特定的方式访问一个过程语言。其参数可能性类似has_table_privilege。希望的访问权限类型必须是USAGE。

has_schema_privilege检查一个用户是否可以以某种特定的方式访问一个模式。其参数可能性类似has_table_privilege。希望的访问权限类型必须是CREATE或USAGE。

has_server_privilege检查一个用户是否可以以某种特定的方式访问一个外部服务器。其参数可能性类似has_table_privilege。希望的访问权限类型必须是USAGE。

has_tablespace_privilege检查一个用户是否可以以某种特定的方式访问一个表空间。其参数可能性类似has_table_privilege。希望的访问权限类型必须是CREATE。

has_type_privilege检查一个用户是否能以特定的方式访问一种类型。其参数的可能性类同于has_table_privilege。在用字符串而不是OID指定类型时,允许的输入和regtype数据类型相同(见Section8.18)。期望的访问特权类型必须等于USAGE。

pg_has_role检查一个用户是否可以以某种特定的方式访问一个角色。其参数可能性类似has_table_privilege,除了public不能被允许作为一个用户名。希望的访问权限类型必须是下列值的某种组合:MEMBER或USAGE。MEMBER表示该角色中的直接或间接成员关系(即使用SETROLE的权力),而USAGE表示不做SETROLE的情况下该角色的权限是否立即可用。

row_security_active检查在current_user的上下文和环境中是否为指定的表激活了行级安全性。表可以用名称或者OID指定。

Table9-61展示了决定是否一个特定对象在当前模式搜索路径中可见的函数。例如,如果一个表所在的模式在当前搜索路径中并且在它之前没有出现过相同的名字,这个表就被说是可见的。这等价于在语句中表可以被用名称引用但不加显式的模式限定。要列出所有可见表的名字:

SELECTrelnameFROMpg_classWHEREpg_table_is_visible(oid);Table9-61.模式可见性查询函数

所有这些函数都要求用对象OID来标识将被检查的对象。如果你想用名称来测试一个对象,使用OID别名类型(regclass、regtype、regprocedure、regoperator、regconfig或regdictionary)将会很方便。例如:

SELECTpg_type_is_visible('myschema.widget'::regtype);注意以这种方式测试一个非模式限定的类型名没什么意义—如果该名称完全能被识别,它必须是可见的。

Table9-62列出了从系统目录抽取信息的函数。

Table9-62.系统目录信息函数

pg_get_keywords返回一组记录描述服务器识别的SQL关键字。word列包含关键字。catcode列包含一个分类码:U为未被预定,C为列名,T类型或函数名,R为预留。catdesc列包含一个可能本地化的描述分类的字符串。

pg_get_constraintdef、pg_get_indexdef、pg_get_ruledef和pg_get_triggerdef分别重建一个约束、索引、规则或触发器的创建命令(注意这是一个反编译的重构,而不是命令的原始文本)。pg_get_expr反编译一个表达式的内部形式,例如一个列的默认值。在检查系统目录内容时有用。如果表达式可能包含Var,在第二个参数中指定它们引用的关系的OID;如果不会出现Var,第二个参数设置为0即可。pg_get_viewdef重构定义一个视图的SELECT查询。这些函数的大部分都有两种变体,一种可以可选地"优质打印"结果。优质打印的格式可读性更强,但是默认格式更可能被未来版本的PostgreSQL以相同的方式解释。在转出目的中避免使用优质打印输出。为优质打印参数传递假将得到和不带该参数的变体相同的结果。

pg_get_functiondef为一个函数返回一个完整的CREATEORREPLACEFUNCTION语句。pg_get_function_arguments返回一个函数的参数列表,形式按照它们出现在CREATEFUNCTION中的那样。pg_get_function_result类似地返回函数的合适的RETURNS子句。pg_get_function_identity_arguments返回标识一个函数必要的参数列表,形式和它们出现在ALTERFUNCTION中的一样。这种形式忽略默认值。

pg_get_userbyid抽取给定OID的角色的名称。

pg_index_column_has_property、pg_index_has_property和pg_indexam_has_property返回指定的索引列、索引或者索引访问方法是否具有指定性质。如果性质的名称找不到或者不适用于特定的对象,亦或者OID或者列号不表示合法的对象,则返回NULL。列的性质可参见Table9-63,索引的性质可参见Table9-64,访问方法的性质可参见Table9-65(注意扩展访问方法可以为其索引定义额外的性质)。

Table9-63.索引列属性

Table9-64.索引性质

当传入pg_class.reloptions或pg_attribute.attoptions时,pg_options_to_table返回存储选项名称/值对(option_name/option_value)的集合。

pg_tablespace_databases允许一个表空间被检查。它返回一组数据库的OID,这些数据库都有对象存储在该表空间中。如果这个函数返回任何行,则该表空间为非空并且不能被删除。为了显示该表空间中的指定对象,你将需要连接到pg_tablespace_databases标识的数据库并且查询它们的pg_class目录。

SELECTpg_typeof(33);pg_typeof-----------integer(1row)SELECTtyplenFROMpg_typeWHEREoid=pg_typeof(33);typlen--------4(1row)表达式collationfor返回传递给它的值的排序规则。例子:

SELECTcollationfor(description)FROMpg_descriptionLIMIT1;pg_collation_for------------------"default"(1row)SELECTcollationfor('foo'COLLATE"de_DE");pg_collation_for------------------"de_DE"(1row)值可能被加上引号并且变成模式限定的。如果从参数表达式得不到排序规则,则返回一个空值。如果参数不是一个可排序的数据类型,则抛出一个错误。

to_regclass、to_regproc、to_regprocedure,to_regoper、to_regoperator、to_regtype、to_regnamespace和to_regrole函数把关系、函数、操作符、类型、模式和角色的名称(以text给出)分别转换成、regclass、regproc、regprocedure、regoper、regoperator、regtype、regnamespace和regrole对象。这些函数与text转换的不同在于它们不接受数字OID,并且在名称无法找到时不会抛出错误而是返回空。对于to_regproc和to_regoper,如果给定名称匹配多个对象时返回空。

Table9-66列出了与数据库对象标识和定位有关的函数。

Table9-66.对象信息和定位函数

pg_describe_object会返回一个数据库对象的文本描述,它由目录OID、对象OID和一个(可能为零的)子对象ID所指定。这种描述是为了人类可读的,并且可能是被翻译过的,具体取决于服务器配置。这有助于确定一个存储在pg_depend目录中的对象的标识。

pg_identify_object_as_address返回一行,其中包含有足以唯一标识由目录OID、对象OID和一个(可能为零的)子对象ID指定的数据库对象的信息。返回的信息独立于当前服务器,也就是说,它可以被用来在另一个服务器中标识一个具有相同命名的对象。type标识数据库对象的类型;name和args是文本数组,它们一起构成了对对象的引用。这三个列可以被传递给pg_get_object_address以获得该对象的内部地址。这个函数是pg_get_object_address的逆函数。

pg_get_object_address返回一行,其中包含有足以唯一标识由类型、对象名和参数数组指定的数据库对象的信息。返回值可以被用在诸如pg_depend等系统目录中并且可以被传递给pg_identify_object或pg_describe_object等其他系统函数。catalog_id是包含该对象的系统目录OID;object_id是对象本身的OID,而object_sub_id是子对象ID,如果没有则为零。这个函数是pg_identify_object_as_address的逆函数。

Table9-67中展示的函数抽取注释,注释是由COMMENT命令在以前存储的。如果对指定参数找不到注释,则返回空值。

col_description为一个表列返回注释,该表列由所在表的OID和它的列号指定(obj_description不能被用在表列,因为表列没有自己的OID)。

obj_description的双参数形式返回一个由其OID和所在系统目录名称指定的数据库对象的注释。例如,obj_description(123456,'pg_class')将会检索出OID为123456的表的注释。obj_description的单参数形式只要求对象OID。它已经被废弃,因为无法保证OID在不同系统目录之间是唯一的;这样可能会返回错误的注释。

shobj_description用起来就像obj_description,但是前者是用于检索共享对象上的注释。某些系统目录对于一个集簇中的所有数据库是全局的,并且其中的对象的描述也是全局存储的。

Table9-68中展示的函数以一种可导出的形式提供了服务器事务信息。这些函数的主要用途是判断在两个快照之间哪些事务被提交。

内部事务ID类型(xid)是32位宽并且每40亿个事务就会回卷。但是,这些函数导出一种64位格式,它被使用一个"世代"计数器,这样在一个安装的生命期内不会回卷。这些函数使用的数据类型txid_snapshot存储了在一个特定时刻有关事务ID可见性的信息。它的成分在Table9-69中描述。

Table9-69.快照成分

txid_snapshot的文本表示是xmin:xmax:xip_list。例如10:20:10,14,15表示xmin=10,xmax=20,xip_list=10,14,15。

Table9-70中展示的函数提供了有关于已经提交事务的信息。这些函数主要提供有关事务何时被提交的信息。只有当track_commit_timestamp配置选项被启用时它们才能提供有用的数据,并且只对已提交事务提供数据。

Table9-70.已提交事务信息

Table9-71.控制数据函数

pg_control_checkpoint返回一个Table9-72中所示的记录

Table9-72.pg_control_checkpoint列

pg_control_system返回一个Table9-73中所示的记录

Table9-73.pg_control_system列

pg_control_init返回一个Table9-74中所示的记录

Table9-74.pg_control_init列

pg_control_recovery返回一个Table9-75中所示的记录

Table9-75.pg_control_recovery列

26.系统管理函数

这一节描述的函数被用来控制和监视一个PostgreSQL安装。

26.1.配置设定函数

Table9-76展示了那些可以用于查询以及修改运行时配置参数的函数。

Table9-76.配置设定函数

current_setting得到setting_name设置的当前值。它对应于SQL命令SHOW。一个例子:

SELECTcurrent_setting('datestyle');current_setting-----------------ISO,MDY(1row)如果没有名为setting_name的设置,除非提供missing_ok并且其值为true,current_setting会抛出错误。

set_config将参数setting_name设置为new_value。如果is_local设置为true,那么新值将只应用于当前事务。如果你希望新值应用于当前会话,那么应该使用false。它等效于SQL命令SET。例如:

SELECTset_config('log_statement_stats','off',false);set_config------------off(1row)26.2.服务器信号函数

在Table9-77中展示的函数向其它服务器进程发送控制信号。默认情况下这些函数只能被超级用户使用,但是如果需要,可以利用GRANT把访问特权授予给其他用户。

这些函数中的每一个都在成功时返回true,并且在失败时返回false。

pg_cancel_backend和pg_terminate_backend向由进程ID标识的后端进程发送信号(分别是SIGINT或SIGTERM)。一个活动后端的进程ID可以从pg_stat_activity视图的pid列中找到,或者通过在服务器上列出postgres进程(在Unix上使用ps或者在Windows上使用任务管理器)得到。一个活动后端的角色可以在pg_stat_activity视图的usename列中找到。

pg_reload_conf给服务器发送一个SIGHUP信号,导致所有服务器进程重载配置文件。

pg_rotate_logfile给日志文件管理器发送信号,告诉它立即切换到一个新的输出文件。这个函数只有在内建日志收集器运行时才能工作,因为否则就不存在日志文件管理器子进程。subprocess.

26.3.备份控制函数

Table9-78中展示的函数可以辅助制作在线备份。这些函数不能在恢复期间执行(pg_is_in_backup、pg_backup_start_time和pg_xlog_location_diff除外)。

pg_start_backup接受一个参数,这个参数可以是备份的任意用户定义的标签(通常这是备份转储文件将被存储的名字)。当被用在排他模式中时,该函数向数据库集簇的数据目录写入一个备份标签文件(backup_label)和一个表空间映射文件(tablespace_map,如果在pg_tblspc/目录中有任何链接),执行一个检查点,然后以文本方式返回备份的起始事务日志位置。用户可以忽略这个结果值,但是为了可能需要的场合我们还是提供该值。当在非排他模式中使用时,这些文件的内容会转而由pg_stop_backup函数返回,并且应该由调用者写入到备份中去。

postgres=#selectpg_start_backup('label_goes_here');pg_start_backup-----------------0/D4445B8(1row)第二个参数是可选的,其类型为boolean。如果为true,它指定尽快执行pg_start_backup。这会强制一个立即执行的检查点,它会导致I/O操作的峰值,拖慢任何并发执行的查询。

在一次排他备份中,pg_stop_backup会移除标签文件以及pg_start_backup创建的tablespace_map文件(如果存在)。在一次非排他备份中,backup_label和tablespace_map的内容会包含在该函数返回的结果中,并且应该被写入到该备份的文件中(这些内容不在数据目录中)。

pg_switch_xlog移动到下一个事务日志文件,允许当前文件被归档(假定你正在使用连续归档)。返回值是在甘冈完成的事务日志文件中结束事务日志位置+1。如果从上一次事务日志切换依赖没有事务日志活动,pg_switch_xlog不会做任何事情并且返回当前正在使用的事务日志文件的开始位置。

pg_create_restore_point创建一个命名事务日志记录,它可以被用作恢复目标,并且返回相应的事务日志位置。这个给定的名字可以用于recovery_target_name来指定恢复要进行到的点。避免使用同一个名称创建多个恢复点,因为恢复会停止在第一个匹配名称的恢复目标。

你可以使用pg_xlogfile_name_offset从任何上述函数的结果中抽取相应的事务日志文件名称以及字节偏移。例如:

postgres=#SELECT*FROMpg_xlogfile_name_offset(pg_stop_backup());file_name|file_offset--------------------------+-------------00000001000000000000000D|4039624(1row)相似地,pg_xlogfile_name只抽取事务日志文件名。当给定的事务日志位置正好在一个事务日志文件的边界,这些函数都返回之前的事务日志文件的名称。这对管理事务日志归档行为通常是所希望的行为,因为前一个文件是当前需要被归档的最后一个文件。

pg_xlog_location_diff以字节数计算两个事务日志位置之间的差别。它可以和pg_stat_replication或Table9-78中其他的函数一起使用来获得复制延迟。

26.4.恢复控制函数

Table9-79中展示的函数提供有关后备机当前状态的信息。这些函数可以在恢复或普通运行过程中被执行。

Table9-80中展示的函数空值恢复的进程。这些函数只能在恢复过程中被执行。

Table9-80.恢复控制函数

在恢复被暂停时,不会有进一步的数据库改变被应用。如果在热备模式,所有新的查询将看到数据库的同一个一致快照,并且在恢复被继续之前不会有更多查询冲突会产生。

26.5.快照同步函数

PostgreSQL允许数据库会话同步它们的快照。一个快照决定对于正在使用该快照的事务哪些数据是可见的。当两个或者更多个会话需要看到数据库中的相同内容时,就需要同步快照。如果两个会话独立开始其事务,就总是有可能有某个第三事务在两个STARTTRANSACTION命令的执行之间提交,这样其中一个会话就可以看到该事务的效果而另一个则看不到。

为了解决这个问题,PostgreSQL允许一个事务导出它正在使用的快照。只要导出的事务仍然保持打开,其他事务可以导入它的快照,并且因此可以保证它们可以看到和第一个事务看到的完全一样的数据库视图。但是注意这些事务中的任何一个对数据库所作的更改对其他事务仍然保持不可见,和未提交事务所作的修改一样。因此这些事务是针对以前存在的数据同步,而对由它们自己所作的更改则采取正常的动作。

如Table9-81中所示,快照通过pg_export_snapshot函数导出,并且通过SETTRANSACTION命令导入。

Table9-81.快照同步函数

函数pg_export_snapshot保存当前的快照并且返回一个text串标识该快照。该字符串必须被传递(到数据库外)给希望导入快照的客户端。直到导出快照的事务的末尾,快照都可以被导入。如果需要,一个事务可以导出多于一个快照。注意这样做只在READCOMMITTED事务中有用,因为在REPEATABLEREAD和更高隔离级别中,事务在它们的生命期中都使用同一个快照。一旦一个事务已经导出了任何快照,它不能使用PREPARETRANSACTION。

关于如何使用一个已导出快照的细节请见SETTRANSACTION.

26.6.复制函数

Table9-82中展示的函数用于控制以及与复制特性交互。这些函数只限于超级用户使用。

很多这些函数在复制协议中都有等价的命令。

Table9-82.复制SQL函数

26.7.数据库对象管理函数

Table9-83中展示的函数计算数据库对象使用的磁盘空间。

pg_column_size显示用于存储任意独立数据值的空间。

pg_table_size接受一个表的OID或名称,并返回该表所需的磁盘空间,但是排除索引(TOAST空间、空闲空间映射和可见性映射包含在内)

pg_indexes_size接受一个表的OID或名称,并返回附加到该表的所有索引所使用的全部磁盘空间。

pg_database_size和pg_tablespace_size接受一个数据库或表空间的OID或名称,并且返回它们所使用的全部磁盘空间。要使用pg_database_size,你必须具有在指定数据库上的CONNECT权限(默认会被授予)。要使用pg_tablespace_size,你必须具有指定表空间上的CREATE权限,除非它是当前数据库的默认表空间。

pg_relation_size接受一个表、索引或TOAST表的OID或者名称,并且返回那个关系的一个分叉所占的磁盘空间的字节尺寸(注意对于大部分目的,使用更高层的函数pg_total_relation_size或者pg_table_size会更方便,它们会合计所有分叉的尺寸)。如果只得到一个参数,它会返回该关系的主数据分叉的尺寸。提供第二个参数可以指定要检查哪个分叉:

pg_size_pretty可以用于把其它函数之一的结果格式化成一种人类易读的格式,可以根据情况使用字节、kB、MB、GB或者TB。

pg_size_bytes可以被用来从人类可读格式的字符串得到其中所表示的字节数。其输入可能带有的单位包括字节、kB、MB、GB或者TB,并且对输入进行解析时是区分大小写的。如果没有指定单位,会假定单位为字节。

Note:函数pg_size_pretty和pg_size_bytes所使用的单位kB、MB、GB和TB是用2的幂而不是10的幂来定义,因此1kB是1024字节,1MB是10242=1048576字节,以此类推。

上述操作表和索引的函数接受一个regclass参数,它是该表或索引在pg_class系统目录中的OID。你不必手工去查找该OID,因为regclass数据类型的输入转换器会为你代劳。只写包围在单引号内的表名,这样它看起来像一个文字常量。为了与普通SQL名称的处理相兼容,该字符串将被转换为小写形式,除非其中在表名周围包含双引号。

如果一个OID不表示一个已有的对象并且被作为参数传递给了上述函数,将会返回NULL。

pg_relation_filenode接受一个表、索引、序列或TOAST表的OID或名称,返回当前分配给它的"filenode"号。文件结点是关系的文件名的基本组件。对于大多数表结果和pg_class.relfilenode相同,但是对于某些系统目录relfilenode为零,并且必须使用此函数获取正确的值。如果传递一个没有存储的关系(如视图),此函数将返回NULL。

pg_relation_filepath与pg_relation_filenode类似,但是它返回关系的整个文件路径名(相对于数据库集簇的数据目录PGDATA)。

26.8.索引维护函数

Table9-85展示了可用于索引维护任务的函数。这些函数不能在恢复期间执行。只有超级用户以及给定索引的拥有者才能是用这些函数。

Table9-85.索引维护函数

brin_summarize_new_values接收一个BRIN索引的OID或者名称作为参数并且检查该索引以找到基表中当前还没有被该索引汇总的页面范围。对任意一个这样的范围,它将通过扫描那些表页面创建一个新的摘要索引元组。它会返回被插入到该索引的新页面范围摘要的数量。

gin_clean_pending_list接受一个GIN索引的OID或者名字,并且通过把指定索引的待处理列表中的项批量移动到主GIN数据结构来清理该索引的待处理列表。它会返回从待处理列表中移除的页数。注意如果其参数是一个禁用fastupdate选项构建的GIN索引,那么不会做清理并且返回值为0,因为该索引根本没有待处理列表。

26.9.通用文件访问函数

Table9-86中展示的函数提供了对数据库服务器所在机器上的文件的本地访问。只有那些在数据库集簇目录和log_directory目录中的文件可以访问。使用相对路径访问集簇目录里面的文件,以及匹配log_directory配置设置的路径访问日志文件。只有超级用户才能使用这些函数。

Table9-86.通用文件访问函数

所有这些函数都有一个可选的missing_ok参数,它指定文件或者目录不存在时的行为。如果为true,函数会返回NULL(pg_ls_dir除外,它返回一个空结果集)。如果为false,则发生一个错误。默认是false。

pg_ls_dir返回指定目录中所有文件(以及目录和其他特殊文件)的名称。include_dot_dirs指示结果集中是否包括"."和".."。默认是排除它们(false),但是当missing_ok为true时把它们包括在内是有用的,因为可以把一个空目录与一个不存在的目录区分开。

pg_read_file返回一个文本文件的一部分,从给定的offset开始,返回最多length字节(如果先到达文件末尾则会稍短)。如果offset为负,它相对于文件的末尾。如果offset和length被忽略,整个文件都被返回。从文件中读的字节被使用服务器编码解释成一个字符串;如果它们在编码中不合法则抛出一个错误。

pg_read_binary_file与pg_read_file相似,除了前者的结果是一个bytea值;相应地,不会执行编码检查。通过与convert_from函数结合,这个函数可以用来读取一个指定编码的文件:

SELECT*FROMpg_stat_file('filename');SELECT(pg_stat_file('filename')).modification;26.10.咨询锁函数

Table9-87中展示的函数管理咨询锁。

Table9-87.咨询锁函数

pg_advisory_lock锁住一个应用定义的资源,可以使用一个单一64位键值或两个32位键值标识(注意这些两个键空间不重叠)。如果另一个会话已经在同一个资源标识符上持有了一个锁,这个函数将等待直到该资源变成可用。该锁是排他的。多个锁请求会入栈,因此如果同一个资源被锁住三次,则它必须被解锁三次来被释放给其他会话使用。

pg_advisory_lock_shared的工作和pg_advisory_lock相同,不过该锁可以与其他请求共享锁的会话共享。只有想要排他的锁请求会被排除。

pg_try_advisory_lock与pg_advisory_lock相似,不过该函数将不会等待锁变为可用。它要么立刻获得锁并返回true,要么不能立即获得锁并返回false。

pg_try_advisory_lock_shared的工作和pg_try_advisory_lock相同,不过它尝试获得一个共享锁而不是一个排他锁。

pg_advisory_unlock将会释放之前获得的排他会话级别咨询锁。如果锁被成功释放,它返回true。如果锁没有被持有,它将返回false并且额外由服务器报告一个SQL警告。

pg_advisory_unlock_shared的工作和pg_advisory_unlock相同,除了它释放一个共享的会话级别咨询锁。

pg_advisory_unlock_all将释放当前会话所持有的所有会话级别咨询锁(这个函数隐式地在会话末尾被调用,即使客户端已经不雅地断开)。

pg_advisory_xact_lock的工作和pg_advisory_lock相同,不过锁是在当前事务的末尾被自动释放的并且不能被显式释放。

pg_advisory_xact_lock_shared的工作和pg_advisory_lock_shared相同,除了锁是在当前事务的末尾自动被释放的并且不能被显式释放。

pg_try_advisory_xact_lock的工作和pg_try_advisory_lock相同,不过锁(若果获得)是在当前事务的末尾被自动释放的并且不能被显式释放。

pg_try_advisory_xact_lock_shared的工作和pg_try_advisory_lock_shared相同,不过锁(若果获得)是在当前事务的末尾被自动释放的并且不能被显式释放。

27.触发器函数

当前PostgreSQL提供一个内建的触发器函数suppress_redundant_updates_trigger,它将阻止任何不会实际更改行中数据的更新发生,这与正常的行为不管数据是否改变始终执行更新相反(这是正常的行为,使得更新运行速度更快,因为不需要检查,并在某些情况下也是有用的)。

suppress_redundant_updates_trigger函数可以像这样被加到一个表:

CREATETRIGGERz_min_updateBEFOREUPDATEONtablenameFOREACHROWEXECUTEPROCEDUREsuppress_redundant_updates_trigger();在大部分情况下,你可能希望在最后为每行触发这个触发器。考虑到触发器是按照名字顺序被触发,你需要选择一个位于该表所有其他触发器之后的触发器名字。

28.事件触发器函数

PostgreSQL提供了这些助手函数来从事件触发器检索信息。

更多有关事件触发器的信息请见Chapter38。

28.1.在命令结束处捕捉更改

当在一个ddl_command_end事件触发器的函数中调用时,pg_event_trigger_ddl_commands返回被每一个用户动作执行的DDL命令的列表。如果在其他任何环境中调用这个函数,会发生错误。pg_event_trigger_ddl_commands为每一个被执行的基本命令返回一行,某些只有一个单一SQL句子的命令可能会返回多于一行。这个函数返回下面的列:

28.2.处理被DDL命令删除的对象

pg_event_trigger_dropped_objects可以被这样用在一个事件触发器中:

CREATEFUNCTIONtest_event_trigger_for_drops()RETURNSevent_triggerLANGUAGEplpgsqlAS$$DECLAREobjrecord;BEGINFORobjINSELECT*FROMpg_event_trigger_dropped_objects()LOOPRAISENOTICE'%droppedobject:%%.%%',tg_tag,obj.object_type,obj.schema_name,obj.object_name,obj.object_identity;ENDLOOP;END$$;CREATEEVENTTRIGGERtest_event_trigger_for_dropsONsql_dropEXECUTEPROCEDUREtest_event_trigger_for_drops();28.3.处理表重写事件

ThefunctionsshowninTable9-88中所示的函数提供刚刚被调用过table_rewrite事件的表的信息。如果在任何其他环境中调用,会发生错误。

Table9-88.表重写信息

可以在一个这样的事件触发器中使用pg_event_trigger_table_rewrite_oid函数:

THE END
1.广州如何免费查询违章车辆上网查询,在网上搜索“车辆违章”或者直接搜“车辆违章广州”,还有 hao123 等综合网站的“实用查询”,进入各地的公安交警网查询系统,按要求输入车辆识别号,有的地区需要注册,方便后续登录查询。 打电话查询,很多地区交警网站会有免费交通违章查询电话,也可拨打 114 进行查询。 直接到所在城市交警队查询,拿着行驶证、https://www.pcauto.com.cn/ask/403988.html
2.65个车牌号字符模板20*40开发实例源码下载65个车牌号字符模板20*40,不含字母I和O,以为可能跟数字1和0混淆。全部为二值化图片,背景色为黑,前景色为白。可用于车牌号识别技术中的模板匹配。 【实例截图】 【核心代码】 65个车牌号字符模板 └── 65个车牌号字符模板 ├── 0.bmp ├── 1.bmp https://www.haolizi.net/example/view_124597.html
3.65个车牌号字符模板20*4065个车牌号字符模板20*40评分: 65个车牌号字符模板20*40,不含字母I和O,以为可能跟数字1和0混淆。全部为二值化图片,背景色为黑,前景色为白。可用于车牌号识别技术中的模板匹配。 车牌号 数字 字母 模板2014-12-27 上传大小:18KB 所需:45积分/C币 https://www.iteye.com/resource/bailichun19901111-8306831
4.65个车牌号字符模板20*40车牌字符模板资源车牌号字符模板是计算机视觉领域中用于车牌号码识别(LPR, License Plate Recognition)的关键元素。在这个场景下,我们有65个特定设计的字符模板,尺寸为20像素宽乘以40像素高。这些模板是二值化的图像,意味着它们只包含两种颜色:黑色背景和白色前景。这种设计有助于简化图像处理,使字符与背景形成鲜明对比,方便后续的特征https://download.csdn.net/download/weixin_42132177/85299590
5.javaopencv车牌车牌识别opencv代码车牌提取 车牌处理提取各字符 模板匹配 识别车牌第一个中文 识别车牌第二字字母 字母或数字 将识别结果显示出来 车牌倾斜提取 直线拟合找斜率 字符分割方法 字符水平方向的切割 目的:去除车牌边框和铆钉的干扰 中间较为密集的地方就是车牌有字符的地方,从而很好的去除了牌边框及铆钉 字符垂直方向的切割 从直方图中可以https://blog.51cto.com/u_16099347/9535046
6.车牌字符模板,JPG格式,40*20车牌字符模板,JPG格式,40*20车牌识别的车牌(不包含I和O)字符模板,图片格式为JPEG,图片尺寸大小为40x20. 本软件ID:10357554 文件下载 立即下载 资源详情 (67个子文件75KB)车牌字符模板,JPG格式,40*20 字符模板(4020)评论信息 fanerye2017: 不错,好东西2018-09-28 https://csdn.hk8.net/detail/weixin_42011121/10357554.html
7.用于车牌识别的字符模板,数字,字母,省简称,20*40大小用于车牌识别的字符模板,数字,字母,省简称,20*40大小_二十大小字母,关于各省车牌识别-C++工具类资源花黎**ma 上传45.89 KB 文件格式 zip 车牌识别 opencv 模板匹配 C++ 用于车牌识别的字符模板,数字,字母,省简称,20*40大小 点赞(0) 踩踩(0) 反馈 所需:3 积分 电信网络下载 https://www.coder100.com/index/index/content/id/973831
8.车牌识别算法与系统(精选八篇)在车牌字符识别环节, 本文使用多模板匹配的方法。模板匹配的主要特点是实现简单,当字符较规整时对字符图像的缺损、污迹干扰适应力强且识别率相当高。目前,我国的车辆牌照字符按顺序依次排列,第一个字符为汉字,一般为省份的简称;第二个字符为英文大写字母,第三、四个字符为英文字母和阿拉伯数字的混编,第五至至第七个https://www.360wenmi.com/f/cnkey8h0mzhn.html
9.word办公技巧说说(办公软件操作技巧:Word文档实用技巧100例,建议但是每次打开后字体默认大小都是五号,每次都还得手动去切换一下,变为常用的四号字大小,要是能打开文档后默认的字体大小为四号就方便了,其实在文档编辑区域空白处右击鼠标,在弹出的快捷菜单中选择“字体”打开字体设置窗口,设置好字体和字号大小为“四号”,然后点击左下角“默认”按钮,在弹出一个新对话框中单击“http://www.cnglyh.com/bangong/14761.html
10.JavaScript使用技巧精萃[代码非常实用]javascript技巧(五).DataGrid中加CheckBox控件模板列. 请看: http://blog.csdn.net/chengking/archive/2005/10/08/497520.aspx (六). window.open() 方法 语法:window.open(pageurl,name,parameters); window对象的open()方法用于创建一个新的窗口实例,新创建的窗口的外观由参数:parameters指定。新窗口中打开的文档由参数:https://www.jb51.net/article/16563.htm
11.车牌号识别设计原理车牌字符分割算法和光学字符识别算法等。某些牌照识别系统还具有通过视频图 像判断车辆驶入视野的功能称之为视频车辆检测。一个完整的牌照识别系统应包 括车辆检测、图像采集、牌照识别等几部分。当车辆检测部分检测到车辆到达时 触发图像采集单元,采集当前的视频图像。牌照识别单元对图像进行处理,定位 https://www.yoojia.com/ask/17-11665331812464996484.html
12.光学字符识别范文7篇(全文)光学字符识别(Optical Character Recognition,OCR),在金融、证券、保险、税务、海关、电信、医疗以及政府和公共事业等其他众多领域中得到越来越广泛的应用,有大量的潜在用户和非常好的市场前景,识别准确度与速度至关重要。特征提取与识别是光学字符识别的根本与热点所在,也是本文的研究重点。 https://www.99xueshu.com/w/ikey94ru0yq9.html
13.银符考试题库在线练习22. 下列字符中,ASCⅡ码最小的是 。 A.K B.a C.h D.H A B C D 23. 计算机字长为32位40. 打开Word 2003,将进入一个新建文档“文档1”,当执行“文件”菜单中的“保存”命令后 。 A.该20. 计算机感染病毒后,以下有关传染的说法中,正确的是 。 A.可以利用系统环境进行自我复制,使自身数量http://www.cquc.net:8089/YFB12/examTab_getExam.action?su_Id=5&ex_Id=4790
14.网页HTML特殊字符编码对照表Indian Rupee Sign ? U+020B9 &#x20B9; ₹ \20B9 Ruble Sign ? U+020BD &#x20Uppercase A A U+00041 A A \0041 Uppercase B B U+00042 B B \0042Left Parenthesis ( U+00028 ( ( ( \0028 Right Parenthesis ) U+00029 &#x29https://www.22vd.com/33993.html
15.中国共产党威海市委员会组织部经验交流PPT演示文稿的基本操作PowerPoint中拥有很多设计模板,并提供了不少漂亮的背景,选择"格式"→"背景",再选中"忽略母版的背景图形"复选框。如果只是想选择颜色来填充,只要单击弹出式下拉菜单,选择"填充效果",当然也可选择"其他颜色"。如果还想更漂亮点,那就在弹出对话框中的过渡、纹理、图案、图片四个标签中来选择。设置完成后,只要单击"确http://www.whzzb.gov.cn/art/2014/7/15/art_34385_941618.html
16.盘锦市交通运输数智执法系统建设项目招标公告2021年01月20日,交通运输部办公厅印发《交通运输综合行政执法队*素质能力提升三年行动方案(2021—2023年)》(交办法〔2021〕5号),夯实基层基础领域提出推进“四基四化”建设,深入推进以“基层执法队*职业化、基层执法站所标准化、基础管理制度规范化、基层执法工作信息化”为内容的“四基四化”建设。对于已经完成交通https://www.ixbang.com/bid/detail/006628CC275C2C0EAF9705DA0CA65FAB.html