下面是一些关于这些运算符的实例: (1)'abc' ~ 'abc' 结果为true (2)'abc' ~ '^a' 结果为true (3)'abc' ~ '(b|d)' 结果为true (4)'abc' ~ '^(b|c)' 结果为false
PostgresSQL支持两种POSIX正则表达式:基本的正则表达式和扩展的正则表达式(POSIX 1003.2)。数据库参数regex_flavor用来控制系统使用基本的正则表达式还是扩展的正则表达式,如果它的值是basic,系统使用基本的正则表达式,如果它的值是extended,系统使用扩展的正则表达式。关于POSIX正则表达式的详细信息,请查阅相关资料,此处不再赘述。数据库对正则表达式的长度没有限制。
substring用来从一个字符串string中提取一个符合正则表达式pattern的字串,如果pattern中含有用括号括起来的子表达式,则返回符合匹配括号中的子表达式的子串。如果string中不存在匹配pattern的子串,则返回空,例如: substring('foobar' from 'o.b') 结果为oob substring('foobar' from 'o(.)b') 结果为o
regexp_replace('fooBarbaz', 'b..', 'X','i') 结果为fooXbaz regexp_replace('fooBarbaz', 'b..', 'X') 结果为fooBarX regexp_replace('foobarbaz', 'b..', 'X') 结果为fooXbaz regexp_replace('foobarbaz', 'b..', 'X', 'g') 结果为fooXX regexp_replace('fooBarbaz', 'b..', 'X','ig') 结果为fooXX
(1)SELECT regexp_matches('foobarbequebaz', '(bar)(beque)'); regexp_matches ---------------- {bar,beque} (1 row)
(2)SELECT regexp_matches('foobarbequebaz', 'barbeque'); regexp_matches ---------------- {barbeque} (1 row)
(1)SELECT foo FROM regexp_split_to_table('the quick brown fox jumped over the lazy dog', E'///s+') AS foo; foo -------- the quick brown fox jumped over the lazy dog (9 rows)
(2)SELECT regexp_split_to_array('the quick brown fox jumped over the lazy dog', E'//s+'); regexp_split_to_array ------------------------------------------------ {the,quick,brown,fox,jumped,over,the,lazy,dog} (1 row)
(3)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)
7.8 数据类型格式化函数PostgreSQL提供了丰富的函数将不同的数据类型转换成字符串类型,同时进行输出格式变换,也可以将字符串转换成其它的数据类型。表7-17列出了所有的这些函数,这些函数的第一个参数是要被格式化的值,第二个参数是定义输出或输入字符串格式的模板。 函数to_timestamp可以将用双精度类型表示的Unix epoch时间转换成timestamp with time zone类型。对于用整数类型表示的Unix epoch,先将它转换成双精度类型,然后再转换成timestamp with time zone类型。
将非字符串类型的数据转换成字符串类型的数据时,输出模板字符串中的字符如果不是模板模式,将被原封不动地复制到输出的结果中。相应地,将字符串类型的数据转换成非字符串类型的数据时,不属于输入模板字符串确定的字符串的字符也将被忽略。 表7-18列出了日期/时间类型格式化模板模式。
有些修饰符可以改变模板模式的行为,表7-19列出了适用于日期/时间类型模板模式的修饰符。
日期/时间类型数据格式化注意事项: (1)FM去掉字符串头部的零和字符串尾部的空格。 (2)TM不会修改字符串末尾的空格。 (3)如果没有使用FX修饰符, to_timestamp 和to_date会自动跳过输入字符串中的多余的空格。如果使用了FX修饰符,FX必须出现在模板字符串的最前面,而且输入的字符串中不能有多余的空格,年月日只能用一个空格分开。例如,to_timestamp('2000 JUN', 'YYYY MON')是正确的,但to_timestamp('2000 JUN', 'FXYYYY MON')是错误的,系统会报错。 (4)to_char中的模板字符串会被直接输出,如果想直接输出某个模式字符串,可以用双引号将模式字符串括起来。例如,对于'"Hello Year "YYYY', “Hello Year”将会被直接输出,而YYYY将被替换成具体的年数据。 (5)如果想输出一个双引号,前面必须加上一个反斜杠。例如,E'//"YYYY Month//"(注意要用两个反斜杠,原因参考字符串语法)。 (6)将一个字符串转换成timestamp或date类型时,在默认的情况下,系统认为年的数据位是4个。如果表示年的数据位超过5个,应该在输入的字符串中用一个非数字的字符将表示年的子串和剩下的子串隔开。例如, to_date('200021131', 'YYYYMMDD')的结果中年将是2000,但to_date('20000-1131', 'YYYY-MMDD') 和to_date('20000Nov31', 'YYYYMonDD')的结果中年将是20002。 (7)将一个字符串转换成timestamp或date类型时,如果模板字符串中有YYY、 YYYY 或Y,YYY,CC将被忽略。如果CC和YY或Y一起使用,那么年将用下面的公式(CC-1)*100+YY来计算。 (8)使用to_timestamp和to_char将字符串转换成ISO类型的日期数据时,有两种使用格式: a)年、星期和一个星期中天编号。例如to_date('2006-42-4', 'IYYY-IW-ID')返回日期2006-10-19,如果忽略天,则默认是1。 b)年和一年中的天编号。例如to_date('2006-291', 'IYYY-IDDD')返回2006-10-19。 (9)将字符串转换成timestamp类型时,微妙和毫秒的计算方法将用一些实例来说明。例如,to_timestamp('12:3', 'SS:MS')表示12秒和300微妙,因为微妙的计算方法是0.3*1000。同样,to_timestamp('12:3', 'SS:MS')、to_timestamp('12:30', 'SS:MS')和to_timestamp('12:300', 'SS:MS')也表示12秒和300微妙,而to_timestamp('12:003', 'SS:MS')则表示12秒3微妙。再看一个更复杂的例子,to_timestamp('15:12:02.020.001230', 'HH:MI:SS.MS.US')表示15小时12分钟2秒中200微妙和1230毫秒,其中001230表示0.001230秒,所以一共有0.001230*1000000=1230毫秒。 (10)to_char(..., 'ID')结果中表示天的部分与 extract('isodow', ...)的结果中表示天的部分是一样的,但to_char(..., 'D')的结果中表示天的部分与extract('dow', ...)的结果中表示天的部分不相同。
表7-20列出了数值类型的格式化模板模式。
数值类型数据格式化注意事项: (1)如果使用模式s,则正负号紧挨着数值被输出,如果使用SG、PL或 MI正负号不一定紧挨着数值被输出。例如,to_char(-12, 'S9999')的结果是' -12',但to_char(-12, 'MI9999')的结果是'- 12'。 (2)9代表一个十进制位,如果模板中的某个9对应的数字位不存在,系统将会输出一个空格, 例如,to_char(-12, 'S9999') 的结果是' -12'。 (3)TH 对于负数和分数没有任何作用。 (4)PL、SG和TH是PostgreSQL扩展特性。 (5)V 的作用是把输入的数值乘以 10的n次方, n是跟在v后面的数值位的个数。小数点和v不能同时出现在to_char的格式化模板字符串中, 例如,99.9V99是不合法的。 表7-21是一些to_char类型函数的实例。
7.9 日期/时间函数和运算符表7-22列出了处理理日期/时间类型数据的运算符。表7-23列出了用于处理日期/时间类型数据的函数,这些函数细节将在后面详细介绍。所有的函数和运算符的参数的类型可以是time或timestamp。表7-24列出了表7-23中的函数的实例。
表7-24. 日期/时间函数实例
PostgreSQL还支持SQL标准中的OVERLAPS运算符,它有两种使用方式: (1)(start1, end1) OVERLAPS (start2, end2) (2)(start1, length1) OVERLAPS (start2, length2) 如果两个时间段表示的时间范围有重叠的部分,上面的两个表达式返回真,否则返回假。例如: (1)SELECT (DATE '2001-02-16', DATE '2001-12-21') OVERLAPS (DATE '2001-10-30', DATE '2002-10-30'); 结果为真 (2)SELECT (DATE '2001-02-16', INTERVAL '100 days') OVERLAPS (DATE '2001-10-30', DATE '2002-10-30'); 结果为假
将一个timesatamp类型的值与一个interval类型的值相加或相减的时候,两个数值的表示天的部分会直接相加或相减,不考虑夏时制的影响,但表示小时的部分相加或相减时可能会考虑夏时制的影响(要求会话的时区能够识别夏时制),所以有时候,interval '1 day'和 interval '24 hours'可能不等价。 假设会话的时区是CST7CDT,timestamp with time zone '2005-04-02 12:00-07' + interval '1 day'的结果是timestamp with time zone '2005-04-03 12:00-06'。但timestamp with time zone '2005-04-02 12:00-07'+ interval '24 hours'的结果却是timestamp with time zone '2005-04-03 13:00-06',因为在时区CST7CDT中,在2005-04-03 02:00有夏时制调整。 7.9.1 函数EXTRACT和 date_partextract函数从日期/时间数据中提取某个域的值,例如年、小时等。source的数据类型必须是timestamp、time或interval(date类型的表达式会被转化成timestamp类型,所以也可以使用)。field指定要选择的域的名称。函数返回值的类型是double precision。下面是合法的 field的名称:
(1)century 表示世纪。例如: SELECT EXTRACT(CENTURY FROM TIMESTAMP '2000-12-16 12:21:13'); 结果: 20 SELECT EXTRACT(CENTURY FROM TIMESTAMP '2001-02-16 20:38:40'); 结果: 21
(2)day 表示天,取值是1到31。例如: SELECT EXTRACT(DAY FROM TIMESTAMP '2001-02-16 20:38:40'); 结果: 16
(3)decade 表示10年,用年除以10。例如: SELECT EXTRACT(DECADE FROM TIMESTAMP '2001-02-16 20:38:40'); 结果: 200
(4)dow 一个星期中天的编号,取值从0到6,0表示星期天,6表示星期六。例如: SELECT EXTRACT(DOW FROM TIMESTAMP '2001-02-16 20:38:40'); 结果: 5
(5)doy 一年中天的编号,取值从0到365/366。例如: SELECT EXTRACT(DOY FROM TIMESTAMP '2001-02-16 20:38:40'); 结果: 47
(6)epoch 对于date和timestamp类型的数据,返回从 1970-01-01 00:00:00-00到现在经过的秒数(可以是负数)。对于interval类型的数据,返回这个interval包含的所有秒数。例如: SELECT EXTRACT(EPOCH FROM TIMESTAMP WITH TIME ZONE '2001-02-16 20:38:40-08'); 结果: 982384720
SELECT EXTRACT(EPOCH FROM INTERVAL '5 days 3 hours'); 结果: 442800 也可以将epoch值转换为timestamp类型的值。例如: SELECT TIMESTAMP WITH TIME ZONE 'epoch' + 982384720 * INTERVAL '1 second';
(7)hour 表示小时,取值范围从0到23。例如: SELECT EXTRACT(HOUR FROM TIMESTAMP '2001-02-16 20:38:40'); 结果: 20
(8)isodow 表示一个星期中天的编号,取值范围从1到7,1表示星期一,7表示星期天。例如: SELECT EXTRACT(ISODOW FROM TIMESTAMP '2001-02-18 20:38:40'); 结果: 7
(9)isoyear 表示年,以ISO 8601为标准。例如: SELECT EXTRACT(ISOYEAR FROM DATE '2006-01-01'); 结果: 2005 SELECT EXTRACT(ISOYEAR FROM DATE '2006-01-02'); 结果: 2006
(10)microseconds 表示毫妙。例如: SELECT EXTRACT(MICROSECONDS FROM TIME '17:12:28.5'); 结果: 28500000
(11)millennium 表示千年。例如: SELECT EXTRACT(MILLENNIUM FROM TIMESTAMP '2001-02-16 20:38:40'); 结果: 3 第三个千年从2001年1月1日开始。
(12)milliseconds 表示微妙。例如: SELECT EXTRACT(MILLISECONDS FROM TIME '17:12:28.5'); 结果: 28500
(13)minute 表示分钟。取值范围0到59。例如: SELECT EXTRACT(MINUTE FROM TIMESTAMP '2001-02-16 20:38:40'); 结果: 38
(14)month 表示月。对于timestamp类型的值,返回一年中的月编号(1到12)。对于interval类型的值,用该值中包含的所有的月的个数对12取模,结果在0到11之间。例如: SELECT EXTRACT(MONTH FROM TIMESTAMP '2001-02-16 20:38:40'); 结果: 2
SELECT EXTRACT(MONTH FROM INTERVAL '2 years 3 months'); 结果: 3
SELECT EXTRACT(MONTH FROM INTERVAL '2 years 13 months'); 结果: 1
(15)quarter 表示季度。取值范围是1到4。例如: SELECT EXTRACT(QUARTER FROM TIMESTAMP '2001-02-16 20:38:40'); 结果: 1
(16)second 表示秒,包括小数部分。取值范围一般是0到59, 如果操作系统支持闰秒(leap second),取值范围是0到60。例如: SELECT EXTRACT(SECOND FROM TIMESTAMP '2001-02-16 20:38:40'); 结果: 40
SELECT EXTRACT(SECOND FROM TIME '17:12:28.5'); 结果: 28.5
(17)timezone 表示同UTC时区偏移值,以秒为单位。正数表示UTC东边的时区。负数表示UTC西边的时区。
(18)timezone_hour 时区偏移的小时部分。
(19)timezone_minute 时区偏移的分钟部分。
(20)week 一年中星期的编号(以ISO 8601为标准)。例如: SELECT EXTRACT(WEEK FROM TIMESTAMP '2001-02-16 20:38:40'); 结果: 7
(21)year 表示年。例如: SELECT EXTRACT(YEAR FROM TIMESTAMP '2001-02-16 20:38:40'); 结果: 2001
函数date_part的功能与extract类似,它的参数field的取值与extract一样,例如:
SELECT date_part('day', TIMESTAMP '2001-02-16 20:38:40'); 结果: 16
SELECT date_part('hour', INTERVAL '4 hours 3 minutes'); 结果: 4 7.9.2 date_trunc函数date_trunc 的作用类似于作用于数值类型数据的trunc函数。 date_trunc('field', source)
source是timestamp或interval类型的值表达式(date类型的值会被自动转换为timestamp类型的值,time类型的值会被自动转换为interval类型的值)。Field表示截断操作的精度。返回值的类型是timestamp或interval。进行截断操作时,被截断的域的类型如果是day或month,它的值被设为1,其它的被截断的域的值被设为0。filed的合法取值是:
例如: (1)SELECT date_trunc('hour', TIMESTAMP '2001-02-16 20:38:40'); 结果: 2001-02-16 20:00:00
(2)SELECT date_trunc('year', TIMESTAMP '2001-02-16 20:38:40'); 结果: 2001-01-01 00:00:00 7.9.3 AT TIME ZONE可以使用AT TIME ZONE 将timestamp 类型的值转换到不同的时区。表7-25列出了它的具体用法
可以用字符串来指定时区的类型,也可以用interval来指定时区的类型。例如,'PST' 和INTERVAL '-08:00'。 下面是一些实例 (假定本地的时区是PST8PDT): (1)SELECT TIMESTAMP '2001-02-16 20:38:40' AT TIME ZONE 'MST'; 结果: 2001-02-16 19:38:40-08
(2)SELECT TIMESTAMP WITH TIME ZONE '2001-02-16 20:38:40-05' AT TIME ZONE 'MST'; 结果: 2001-02-16 18:38:40 第一个例子将timestamp without time zone类型的值的时区看成时区为MST的值,然后在将这个值转换成时区为PST的值作为作为结果显示给用户。第二个例子将时区为UTC-5的值抓换成成时区为MST的值,然后再转换成时区为PST的值作为结果显示给用户。 函数timezone(zone, timestamp)的作用与timestamp AT TIME ZONE zone是一样的。 7.9.4 当前日期/时间CURRENT_DATE CURRENT_TIME CURRENT_TIMESTAMP CURRENT_TIME(precision) CURRENT_TIMESTAMP(precision) LOCALTIME LOCALTIMESTAMP LOCALTIME(precision) LOCALTIMESTAMP(precision) now() transaction_timestamp()
在同一个事务内多次调用同一个上面的函数,得到的结果都是一样的。 CURRENT_TIME 和CURRENT_TIMESTAMP 返回带时区的值, LOCALTIME 和LOCALTIMESTAMP返回不带时区的值。 CURRENT_TIME、 CURRENT_TIMESTAMP、 LOCALTIME和LOCALTIMESTAMP 可以带一个表示精度的小数,精度确定了秒的小数位的个数,如果不带精度,秒的精度就是系统的最大精度。 now()和transaction_timestamp()与CURRENT_TIME是等价的。
下面是一些例子: (1)SELECT CURRENT_TIME; 结果: 14:39:53.662522-05 (2)SELECT CURRENT_DATE; 结果: 2001-12-23 (3)SELECT CURRENT_TIMESTAMP; 结果: 2001-12-23 14:39:53.662522-05 (4)SELECT CURRENT_TIMESTAMP(2); 结果: 2001-12-23 14:39:53.66-05 (5)SELECT LOCALTIMESTAMP; 结果: 2001-12-23 14:39:53.662522
statement_timestamp()返回当前语句开始的时间。 clock_timestamp()和timeofday()都返回当前的时间,但它们的返回值的类型不同,一个是字符串,一个是timestamp with time zone。 所有的日期/时间数据类型都接受常量now,它表示当前事务开始的时间。下面的三条命令返回的结果是一样的: SELECT CURRENT_TIMESTAMP; SELECT now(); SELECT TIMESTAMP 'now'; 7.9.5 pg_sleep 函数使用函数pg_sleep让数据库服务进程睡眠指定的时间: pg_sleep(seconds) 参数seconds的单位是秒,类型是double precision。例如: SELECT pg_sleep(1.5);
7.10 枚举类型函数表7-26列出了枚举类型的函数。表7-27列出了枚举类型的函数的实例。表中的例子都以下面的枚举类型为基础: CREATE TYPE rainbow AS ENUM ('red', 'orange', 'yellow', 'green', 'blue', 'purple');
表7-27. 枚举类型函数实例
注意,除了函数enum_range,其它函数不关心参数的值,只关心参数的类型,输入null或者某个枚举类型的值,得到的结果都是一样的。
7.11 几何函数和运算符几何数据类型包括point、 box, 、lseg、 line、 path、 polygon和 circle 。表7-28、表7-29和表7-30列出了和这些类型相关的函数和运算符。
7.12 网络地址函数和运算符表7-31列出了cidr和 inet运算符。运算符<<、 <<=、 >>和>>= 的作用是测试两个子网是否互相包含,它们只考虑两个地址的网络部分,忽略地址的主机部分。
表7-32列出了cidr和inet函数。函数host、text和abbrev的作用是提供不同的显示格式。
任何cidr值都可以显示或隐式地被转换成inet值,所以上面的参数为inet类型的函数也可以接受cidr类型的参数。也可以将inet类型的值转换成cidr类型的值,进行转换时,inet地址中任何网络掩码右边的二进制位都会被设为0。也可以使用类型转换语法将字符串转换成inet或cidr类型。例如,inet(expression) or colname::cidr。
表7-33列出了类型macaddr的函数。函数trunc(macaddr) 将MAC地址的最后三个字节置为0,可以使用它来得到网卡生产厂商的编号。 表7-33. macaddr函数
macaddr 类型也支持标准的比较运算符(>,<=等),排序的规则是按字典顺序。
7.13 XML 函数7.13.1. 产生 XML 文档可以使用下面的函数将sql查询的结果转换成xml文档。 7.13.1.1 xmlcomment函数xmlcomment将字符串text转换成xml注释。Text中不能包含“--”,也不能以 “-” 结尾。如果参数为null,结果也为null。例如: SELECT xmlcomment('hello');
xmlcomment -------------- <!--hello--> 7.13.1.2 xmlconcat
函数xmlconcat将一个或多个xml值连接起来形成一个单一的xml值,空值将被忽略。如果所有的参数都是空值,它将返回空值。例如: SELECT xmlconcat('<abc/>', '<bar>foo</bar>');
xmlconcat ---------------------- <abc/><bar>foo</bar>
如果某个值中存在xml声明,将按如下规则来处理: (1)如果所有的参数都含有同样xml版本声明,那么结果中将包含版本声明,否则结果中将不包含版本声明。 (2)如果所有参数都含有standalone声明,而且它的值是“yes”,结果中也会包含值为“yes”的standalone声明。其它情况下,结果中不会含有standalone声明。 (3)如果结果中需要一个standalone声明,但是参数中没有提供版本声明,结果中的版本声明的值将是1.0。 (4)参数中编码声明在任何情况下都会被忽略,结果中不会含有编码声明。
例如: SELECT xmlconcat('<?xml version="1.1"?><foo/>', '<?xml version="1.1" standalone="no"?><bar/>');
xmlconcat ----------------------------------- <?xml version="1.1"?><foo/><bar/> 7.13.1.3 xmlelementxmlelement(name name [, xmlattributes(value [AS attname] [, ... ])] [, content, ...])
函数根据给定的名字、属性和内容产生一个xml元素。例如: (1)SELECT xmlelement(name foo);
xmlelement ------------ <foo/>
(2)SELECT xmlelement(name foo, xmlattributes('xyz' as bar));
xmlelement ------------------ <foo bar="xyz"/>
(3)SELECT xmlelement(name foo, xmlattributes(current_date as bar), 'cont', 'ent');
xmlelement ------------------------------------- <foo bar="2007-01-26">content</foo>
不是合法的xml名字和属性的字符将会用该字符对应的Unicode编码表示(十六进制),格式是_xHHHH_。例如: SELECT xmlelement(name "foo$bar", xmlattributes('xyz' as "a&b"));
xmlelement ---------------------------------- <foo_x0024_bar a_x0026_b="xyz"/>
如果属性的值是一个列引用,则不需要指定属性的名字,系统默认使用列的名字作为属性的名字。其它的情况下需要指定属性的名字。例如,下面的例子是合法的: CREATE TABLE test (a xml, b xml); SELECT xmlelement(name test, xmlattributes(a, b)) FROM test;
下面的例子是不合法的: SELECT xmlelement(name test, xmlattributes('constant'), a, b) FROM test; SELECT xmlelement(name test, xmlattributes(func(a, b))) FROM test; 如果指定了文档的内容,将会把它转换成xml类型。如果文档内容的类型是xml,则可以构造复杂的xml文档。例如: SELECT xmlelement(name foo, xmlattributes('xyz' as bar), xmlelement(name abc), xmlcomment('test'), xmlelement(name xyz));
xmlelement ---------------------------------------------- <foo bar="xyz"><abc/><!--test--><xyz/></foo> 其它类型文档在被转换成xml类型时,字符<、>和 &将被转换成xml实体。bytea类型的数据将以base64或hex格式表示,选择哪种格式取决于参数xmlbinary的值。 7.13.1.4 xmlforestxmlforest(content [AS name] [, ...])
函数xmlforest 根据给定的名字和内容产生一个xml森林。例如: (1)SELECT xmlforest('abc' AS foo, 123 AS bar);
xmlforest ------------------------------ <foo>abc</foo><bar>123</bar>
(2)SELECT xmlforest(table_name, column_name) FROM information_schema.columns WHERE table_schema = 'pg_catalog';
xmlforest ------------------------------------------------------------------------------------------- <table_name>pg_authid</table_name><column_name>rolname</column_name> <table_name>pg_authid</table_name><column_name>rolsuper</column_name> ... 其它规则与xmlelement相同。 7.13.1.5 xmlpixmlpi(name target [, content])
函数xmlpi产生一个XML处理指令。如果指定了参数content,其中不能含有“?>”。例如: SELECT xmlpi(name php, 'echo "hello world";');
xmlpi ----------------------------- <?php echo "hello world";?> 7.13.1.6 xmlrootxmlroot(xml, version text|no value [, standalone yes|no|no value])
函数xmlroot修改一个xml值的根节点。如果指定了版本,则用它替换参数xml的版本声明。如果指定了standalone值,则用它替换换参数xml的standalone声明。例如:
SELECT xmlroot(xmlparse(document '<?xml version="1.1"?><content>abc</content>'), version '1.0', standalone yes);
xmlroot ---------------------------------------- <?xml version="1.0" standalone="yes"?> <content>abc</content> 7.13.1.7 xmlagg
函数xmlagg的作用类似xmlconcat,将多个xml值连接在一起,它是一个聚集函数。例如: CREATE TABLE test (y int, x xml); INSERT INTO test VALUES (1, '<foo>abc</foo>'); INSERT INTO test VALUES (2, '<bar/>'); SELECT xmlagg(x) FROM test; xmlagg ---------------------- <foo>abc</foo><bar/>
注意在当前的实现中,各个xml值出现的顺序是不确定。如果想确定xml值的顺序,可以使用下面的命令: SELECT xmlagg(x) FROM (SELECT * FROM test ORDER BY y DESC) AS tab; xmlagg ---------------------- <bar/><foo>abc</foo>
7.13.1.8 XML 谓词如果参数的值是 XML文档,则表达式IS DOCUMENT返回真。如果参数是xml内容片段,则返回假。如果参数是NULL,则返回NULL。 7.13.2 处理 XML值函数xpath用来处理xml值, 它处理Xpath表达式 : xpath(xpath, xml[, nsarray])
函数xpath对XML值xml使用XPath表达式xpath进行求值。它返回符合xpath的XML值。第三个参数是一个名字空间映射。它应该是一个二维数组,数组的第二个维的大小必须是2。例如: SELECT xpath('/my:a/text()', '<my:a xmlns:my="http://example.com">test</my:a>', ARRAY[ARRAY['my', 'http://example.com']]);
xpath -------- {test} (1 row) 7.13.3 将表中的数据转换成XML格式下面的函数用于将表中的数据转换成XML的格式,返回值的类型都是xml: (1)table_to_xml(tbl regclass, nulls boolean, tableforest boolean, targetns text) (2)query_to_xml(query text, nulls boolean, tableforest boolean, targetns text) (3)cursor_to_xml(cursor refcursor, count int, nulls boolean, tableforest boolean, targetns text) table_to_xml用于将数据库中的表中的数据转换成XML格式,参数tb1表示表的名称。query_to_xml执行一个查询然后将查询结果过转换成XML格式,参数query表示要执行的查询。cursor_to_xml从参数cursor指定的游标中取出count个数据行,然后将这些数据行转换成XML格式。 对于函数table_to_xml,如果参数tableforest的值是fasle,则结果的格式如下: <tablename> <row> <columnname1>data</columnname1> <columnname2>data</columnname2> </row>
<row> ... </row>
... </tablename>
对于函数table_to_xml,如果参数tableforest的值是true,则结果的格式如下: <tablename> <columnname1>data</columnname1> <columnname2>data</columnname2> </tablename>
<tablename> ... </tablename>
... 对于函数query_to_xml和cursor_to_xml,如果参数tableforest的值是fasle,则结果的格式如下: <table> < table > <columnname1>data</columnname1> <columnname2>data</columnname2> </table >
<table > ... </table>
... </table>
对于函数query_to_xml和cursor_to_xml,如果参数tableforest的值是true,则结果的格式如下: <row > <columnname1>data</columnname1> <columnname2>data</columnname2> </row>
<row> ... </row>
... 将表中的数据转换成XML类型时,规则同函数xmlelement一样。 参数nulls决定空值是否被包含在输出的结果中。如果它的值为假,空值将忽略,不会出现在输出的结果中。被如果它的值是真,列的空值用下面的形式表示: 其中的xsi是XML模式实例的名字空间前缀。 参数targetns决定结果的XML名字空间。如果不想指定任何名字空间,应该把它置为空串。
下面的函数返回XML模式文档,该模式文档描述上面的对应的数据映射函数产生的XML数据: (1)table_to_xmlschema(tbl regclass, nulls boolean, tableforest boolean, targetns text) (2)query_to_xmlschema(query text, nulls boolean, tableforest boolean, targetns text) (3)cursor_to_xmlschema(cursor refcursor, nulls boolean, tableforest boolean, targetns text)
下面的函数将表中的数据转换成xml格式,同时产生一个XML模式文档来描述这些 xml数据: (1)table_to_xml_and_xmlschema(tbl regclass, nulls boolean, tableforest boolean, targetns text) (2)query_to_xml_and_xmlschema(query text, nulls boolean, tableforest boolean, targetns text)
下面的函数用于将一个模式中的所有的表中的数据转换成xml格式: (1)schema_to_xml(schema name, nulls boolean, tableforest boolean, targetns text) (2)schema_to_xmlschema(schema name, nulls boolean, tableforest boolean, targetns text) (3)schema_to_xml_and_xmlschema(schema name, nulls boolean, tableforest boolean, targetns text)
下面的函数用于将一个数据库中的所有的表中的数据转换成xml格式: (1)database_to_xml(nulls boolean, tableforest boolean, targetns text) (2)database_to_xmlschema(nulls boolean, tableforest boolean, targetns text) (3)database_to_xml_and_xmlschema(nulls boolean, tableforest boolean, targetns text)
上面的6个函数会产生大量的数据,会消耗大量的内存。一般情况下,不要使用它们,应该一个表一个表地单独转换,如果单个表中的数据量也比较大,应该使用游标来进行转换。 模式映射的结果如下: <schemaname>
table1-mapping
table2-mapping
...
</schemaname>
数据库映射的结果如下: <dbname>
<schema1name> ... </schema1name>
<schema2name> ... </schema2name>
...
</dbname>
下面列出了一个XSLT样式表,可以用它将table_to_xml_and_xmlschema输出的数据转换成HTML文档: <?xml version="1.0"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://www.w3.org/1999/xhtml" >
<xsl:output method="xml" doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd" doctype-public="-//W3C/DTD XHTML 1.0 Strict//EN" indent="yes"/>
<xsl:template match="/*"> <xsl:variable name="schema" select="//xsd:schema"/> <xsl:variable name="tabletypename" select="$schema/xsd:element[@name=name(current())]/@type"/> <xsl:variable name="rowtypename" select="$schema/xsd:complexType[@name=$tabletypename]/xsd:sequence/xsd:element[@name='row']/@type"/>
<html> <head> <title><xsl:value-of select="name(current())"/></title> </head> <body> <table> <tr> <xsl:for-each select="$schema/xsd:complexType[@name=$rowtypename]/xsd:sequence/xsd:element/@name"> <th><xsl:value-of select="."/></th> </xsl:for-each> </tr>
<xsl:for-each select="row"> <tr> <xsl:for-each select="*"> <td><xsl:value-of select="."/></td> </xsl:for-each> </tr> </xsl:for-each> </table> </body> </html> </xsl:template>
</xsl:stylesheet>
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||