数据类型
复合类型
# 创建一个复合类型person
# 命令格式:create type xxx AS ();
testdb=# create type person AS (
testdb(# name text,
testdb(# age int4,
testdb(# sex boolean
testdb(# );
CREATE TYPE
testdb=# \d person;
合成类型 "public.person"
栏位 | 类型 | Collation | Nullable | Default
------+---------+-----------+----------+---------
name | text | | |
age | integer | | |
sex | boolean | | |
testdb=# \dt person;
没有找到任何名称为 "person" 的关联。
testdb=# \d person;
合成类型 "public.person"
栏位 | 类型 | Collation | Nullable | Default
------+---------+-----------+----------+---------
name | text | | |
age | integer | | |
sex | boolean | | |
# 创建一个带复合类型的表author
testdb=# create table author (
testdb(# id int4,
testdb(# people person,
testdb(# book text
testdb(# );
CREATE TABLE
testdb=# \d author;
数据表 "public.author"
栏位 | 类型 | Collation | Nullable | Default
--------+---------+-----------+----------+---------
id | integer | | |
people | person | | |
book | text | | |
# 插入数据
testdb=# insert into author values(1, ' ("qkl", 29, TRUE)', '张三的自传');
INSERT 0 1
# 缺省不填写就是NULL,逗号间不要有空格
testdb=# insert into author values(2, '("zgq", , TRUE)', '张三的自传2');
ERROR: invalid input syntax for integer: " "
第1行insert into author values(2, '("zgq", , TRUE)', '张三的自传2...
^
testdb=# insert into author values(2, '("zgq",,TRUE)', '张三的自传2');
INSERT 0 1
testdb=# insert into author values(2, '("zgq",, TRUE)', '张三的自传2');
INSERT 0 1
testdb=# insert into author values(3, '("",, TRUE)', '张三的自传3');
INSERT 0 1
# ROW行插入,注意ROW后面的字符请用单引号,不能带双引号
testdb=# insert into author values(4, ROW("",, TRUE), '张三的自传5');
ERROR: zero-length delimited identifier at or near """"
第1行insert into author values(4, ROW("",, TRUE), '张三的自传5');
^
testdb=# insert into author values(4, ROW('PCB',, TRUE), '张三的自传5');
ERROR: syntax error at or near ","
第1行insert into author values(4, ROW('PCB',, TRUE), '张三的自传5...
^
# 省略ROW
testdb=# insert into author values(4, ('hgr',30, TRUE), '张三的自传6');
INSERT 0 1
testdb=# select (people).name from author;
name
------
qkl
zgq
zgq
hgr
(5 行记录)
# 更新复合类型数据,复合类型名不带括号
testdb=# update author set people.name='qkl2' where id=1;
UPDATE 1
testdb=# select people from author;
people
-------------
(zgq,,t)
(zgq,,t)
("",,t)
(hgr,30,t)
(qkl2,29,t)
(5 行记录)
testdb=# update author set people.age = people.age +1 where id=1;
ERROR: missing FROM-clause entry for table "people"
第1行update author set people.age = people.age +1 where id=1;
^
# 如果更新的字段右边也是复合类型必须携带括号
testdb=# update author set people.age = (people).age +1 where id=1;
UPDATE 1
testdb=# select people from author;
people
-------------
(zgq,,t)
(zgq,,t)
("",,t)
(hgr,30,t)
(qkl2,30,t)
(5 行记录)
# 单独插入复合类型的数据
testdb=# insert into author (id, people.name, people.age) values(7, 'ldh', 33);
INSERT 0 1
testdb=# select * from author;
id | people | book
----+-------------+-------------
2 | (zgq,,t) | 张三的自传2
2 | (zgq,,t) | 张三的自传2
3 | ("",,t) | 张三的自传3
4 | (hgr,30,t) | 张三的自传6
1 | (qkl2,30,t) | 张三的自传
7 | (ldh,33,) |
(6 行记录)
XML类型
xm丨类型可以用于存储XML数据。使用字符串类型(如text)也可以存储XML数据,但text类型不能保证其中存储的是合法XML数据,通常需要由应用程序来负责保证输人数据的正确性,这将增加应用程序开发的难度。而使用xml类型就不存在此问题。数据库会对输人的数据进行检查,让一些不符合XML标准的数据不能存放到数据库中,同时还提供了函数对其类型进行安全性检査。
注意,要使用xml数据类型,在编译PostgreSQL源码时必须使用以下参数:
configure --with-libxml
xml存储的XML数据杳两种:
- 由 XML 标准走义的
documents
。 - 由XML标准定义的
content
片段。
content
片段可以有多个级元素或character
节点.但documents
只能有一个顶级元素。可以使用xmlvalue is DOCUMENT
来判断一个特定的XML值是一个documents
还足content
片段。
PostgreSQL的xmlopiions参数用来指定输人的数据是documents
还是content
片段,默认情况下此值为content
片段。所以输人的xml可以有多个顶级元素,但如果把此参数改成document
,将不能输人有多个顶级元素的内容。
PostgreSQL数据库在客户端与服务器之间传递数据时,会自动进行字符集的转换。如果客户端的字符集与服务端不一样,PostgreSQL会自动进行字符集转换。但也正是因为有这个特性,在传递XML数据时需要格外注意。我们知道,对于XML文件来说,可以通过类似“encoding="XXX"”的方式指定自己文件的字符集,但当这些数据在PostgreSQL之间传递时, PostgreSQL会把其原始内容的宇符集变成数据库服务端的字符集,而这就会导致问题,因为这意味着XML数据中的字符集编码声明在客户端和服务器之间传递时,可能变得无效。为了应对该问题,提交输人到xml类型的字符串中的编码声明将会被忽略掉.同时内容的字符集会被认为是当前数据库服务器的字符集。
正确处理XML字符集的方式是,先将XML数据的字符串在当前客户端中编码成当前客户端的字符集,然后再发送到服务端,这样就会被转换成服务端的字符集存储。当査询xml 类型的值时,此数据又会被转换成客户端的字符集,所以客户端收到的XML数据的字符集就是客户端的字符集。
所以通常来说,如果XML数据的字符集编码、客户端字符集编码,以及服务器字符集编码完全一样,那么用PostgreSQL处理XML数据将会大大减少字符集问题,并且处理的效率也会很高。通常XML数据都是用UTF-8编码格式处理的,因此把PostgreSQL数据库服务器端编码也设置成UTF-8将是一种较好的选择。
postgres=# select xml'<code>hello postgres</code>';
xml
-----------------------------
<code>hello postgres</code>
(1 行记录)
postgres=# show xmloption;
xmloption
-----------
content
(1 行记录)
postgres=# set xmloption TO document;
SET
postgres=# show xmloption;
xmloption
-----------
document
(1 行记录)
# document类型,插入多顶级元素,出错
postgres=# select xml'<code>hello postgres</code><other>hello world</other>';
ERROR: invalid XML document
第1行select xml'<code>hello postgres</code><other>hello world</ot...
^
描述: line 1: Extra content at the end of the document
<code>hello postgres</code><other>hello world</other>
^
postgres=# set xmloption TO content;
SET
postgres=# select xml'<code>hello postgres</code><other>hello world</other>';
xml
-------------------------------------------------------
<code>hello postgres</code><other>hello world</other>
(1 行记录)
# xmlparse函数
postgres=# select xmlparse(document'<?xml version="1.0"?><person><name>qkl</name></person>');
xmlparse
-----------------------------------
<person><name>qkl</name></person>
(1 行记录)
postgres=# select xmlparse(content'<?xml version="1.0"?><person><name>qkl</name></person>');
xmlparse
-----------------------------------
<person><name>qkl</name></person>
(1 行记录)
json类型
JSON数据类型是从P〇StgreSQL9.3开始提供的一种类型,9.3版中只有一种类型:JSON
在PosIgreSQL 9.4中乂提供了一种更高效的类型JSONB这两种类型在使用上几乎完全一致,主要的区別是,JSON类型是把输人的数据原封不动地存放到数据库中(当然在存放前会做JSON的语法检查),使用的时候需要®:新解析数据,而JSONB类型是在存放时就把JSON解折成二进制格式了,使用的时候就不需要再次解析,所以JSONB在使用时性能会更高。另外,JSONB支持在其上逑索引,iftHSON则不能,这是JSONB类型的很大一个优点。
因为JSON类型是把输人的整个字符串原封不改动地保存到数据库中的,因此JSON串中key之间多余的空格也会保留。而且,如果JSON串中有重复的key,这些重复的key也会保留(默认处理时以最后一个为准),同时也会保留输人时JSON串中各个key的顺序。而JSONB类塑则恰恰相反,+会保留多余的空格,不会保留key的顺序,也不会保留重复的key。
在PostgreSQL中只允许毎个数据库用一种服务器编码,如果数据库的编码不是UTF-8,PostgreSQL中的JSON类塑是无法严格符合JSON规范中对字符集的要求的。如果输人中包含不能在服务器编码中表示的字符数据,将无法导人到数据库中。但是,能在服务器编码中表示的
非UTF-8字符则是被允许的。可以使用uXXXX形式的转义,从而忽视数据库的字符集编码。
当把一个JSON字符串转换成JSONB类塑吋,JSON字符串内的数据类型实际上被转换成rPostgreSQL数据库中的类塑,两者的映射关系见表5-30。耑要注意的是,如果是在JS0NB中,在PostgrcSQL 不能输人超出numeric数据类型范闹的值。
基础操作
testdb=# select '9'::json, '"osdba"'::json, 'true'::json, 'null'::json;
json | json | json | json
------+---------+------+------
9 | "osdba" | true | null
(1 行记录)
testdb=# select '[9, true, "qkl", null]'::json, '[9, true, "qkl", null]'::jsonb;
json | jsonb
------------------------+------------------------
[9, true, "qkl", null] | [9, true, "qkl", null]
(1 行记录)
testdb=# select json'{"name":"qkl", "age":18, "sex":true, "money":888.88}';
json
------------------------------------------------------
{"name":"qkl", "age":18, "sex":true, "money":888.88}
(1 行记录)
# json 存取的是浮点型,存在精度问题
testdb=# select json'{"p":1.684544545454e-27}';
json
--------------------------
{"p":1.684544545454e-27}
(1 行记录)
# jsonb存取的是numeric
testdb=# select jsonb'{"p":1.684544545454e-27}';
jsonb
--------------------------------------------------
{"p": 0.000000000000000000000000001684544545454}
(1 行记录)
更多和操作符
testdb=# select json'[1,2,3]'->0;
?column?
----------
1
(1 行记录)
testdb=# select json'[1,2,3]'->3;
?column?
----------
(1 行记录)
testdb=# select json'[1,2,3]'->2;
?column?
----------
3
(1 行记录)
testdb=# select json'[1,2,3]'->>2;
?column?
----------
3
(1 行记录)
testdb=# select json'[1,2,3]'->>'2';
?column?
----------
(1 行记录)
testdb=# select json'{"a":1,"b":22}'->>'a';
?column?
----------
1
(1 行记录)
testdb=# select json'{"a":{"a1":{"a11":111}},"b":22}'#>'{a,a1}'
testdb-# ;
?column?
-------------
{"a11":111}
(1 行记录)
testdb=# select json'{"a":{"a1":{"a11":111}},"b":22}'#>'{a,a1,a11}'
testdb-# ;
?column?
----------
111
(1 行记录)
testdb=# select json'{"a":{"a1":{"a11":111}},"b":22}'#>>'{a,a1,a11}';
?column?
----------
111
(1 行记录)
testdb=# select json'{"a":{"a1":{"a11":111}},"b":22}'#>>'{a,a1}';
?column?
-------------
{"a11":111}
(1 行记录)
Range类型
testdb=# select '(0,6)'::int4range;
int4range
-----------
[1,6)
(1 行记录)
testdb=# select '[0,6)'::int4range;
int4range
-----------
[0,6)
(1 行记录)
testdb=# select '[0,6]'::int4range;
int4range
-----------
[0,7)
(1 行记录)
testdb=# select 'empty'::int4range;
int4range
-----------
empty
(1 行记录)
# 上面我们看出,int4range总数会转换成`[)`格式
testdb=# select '[0,6]'::numrange;
numrange
----------
[0,6]
(1 行记录)
testdb=# select '[0,6)'::numrange;
numrange
----------
[0,6)
(1 行记录)
testdb=# select '(0,6)'::numrange;
numrange
----------
(0,6)
(1 行记录)
testdb=# select '(0,)'::numrange;
numrange
----------
(0,)
(1 行记录)
testdb=# select '[1,)'::numrange;
numrange
----------
[1,)
(1 行记录)
数组类型
PostgreSQL支持表的字段使用定长或可变长度的一维或多维数组,数组的类型可以是任何数据库内建的类型、用户自定义的类型、枚举类型,以及组合类型。但目前还不支持domain类型。
create table test6 (id int, col1 int[], col2 int[10], col3 text[][]);
create table test7 (id int, col1 int[10], col2 int[], col3 text[]);
在第一个语句中第二列的声明col2 int[10]
与第二个语句中第二列的声明col2 int[]
其意思相同;而在第一个语句中第三列的声明col3 text[][]
与第二个语句中第三列的声明col3 text[]
的意思也是相同的
我们来查看下表结构
testdb=# create table test6 (id int, col1 int[], col2 int[10], col3 text[][]);
CREATE TABLE
testdb=# create table test7 (id int, col1 int[10], col2 int[], col3 text[]);
CREATE TABLE
testdb=# \d
关联列表
架构模式 | 名称 | 类型 | 拥有者
----------+--------------+--------+----------
public | author | 数据表 | postgres
public | test1 | 数据表 | postgres
public | test2 | 数据表 | postgres
public | test2_id_seq | 序列数 | postgres
public | test3 | 数据表 | postgres
public | test3_id_seq | 序列数 | postgres
public | test6 | 数据表 | postgres
public | test7 | 数据表 | postgres
(8 行记录)
testdb=# \d test6;
数据表 "public.test6"
栏位 | 类型 | Collation | Nullable | Default
------+-----------+-----------+----------+---------
id | integer | | |
col1 | integer[] | | |
col2 | integer[] | | |
col3 | text[] | | |
testdb=# \d test7;
数据表 "public.test7"
栏位 | 类型 | Collation | Nullable | Default
------+-----------+-----------+----------+---------
id | integer | | |
col1 | integer[] | | |
col2 | integer[] | | |
col3 | text[] | | |
testdb=# create table test66(id int, col1 int[]);
CREATE TABLE
testdb=# insert into test66 values(1, '{1,2,3}');
INSERT 0 1
testdb=# insert into test66 values(2, '{4,5,6}');
INSERT 0 1
testdb=# select * from test66;
id | col1
----+---------
1 | {1,2,3}
2 | {4,5,6}
(2 行记录)
testdb=# create table test77(id int, col1 text[]);
CREATE TABLE
testdb=# insert into test77 values(1, '{how, howe, howl}');
INSERT 0 1
testdb=# select * from test77;
id | col1
----+-----------------
1 | {how,howe,howl}
(1 行记录)
testdb=# insert into test77 values(1, '{"how", "howe", "howl"}');
INSERT 0 1
testdb=# select * from test77;
id | col1
----+-----------------
1 | {how,howe,howl}
1 | {how,howe,howl}
(2 行记录)
# 注意上面不同的类型,可能分隔符会不一样,下面可查询不同类型的分隔符
testdb=# select typname,typdelim from pg_type where typname in ('int4', 'int8', 'bool', 'char', 'box');
typname | typdelim
---------+----------
bool | ,
char | ,
int8 | ,
int4 | ,
box | ;
(5 行记录)
testdb=# create table test778(id int ,col1 box[]);
CREATE TABLE
testdb=# insert into test778 values(1, '{((1,1), (2,2)); ((3,3),(4,4))}');
INSERT 0 1
testdb=# select * from test778;
id | col1
----+---------------------------
1 | {(2,2),(1,1);(4,4),(3,3)}
(1 行记录)
# 上面输人的字符串内容是没有空格的,在有空格时,乂该如何输人呢?见下面的例子:
testdb=# insert into test77 values(3,'{how many,how mach,how old}');
INSERT 0 1
可以看到有空格,也可以直接输人。
那么字符串中有逗号时怎么办呢?这时可以使用双引号,如下:
testdb=# insert into test77 values(4,'{"who, what", "CO.,LTD."}');
INSERT 0 1
如果字符串中有单引号怎么办呢?这时可以使用两个连接的单引号表示一个单引号:
testdb=# insert into test77 values(3,'{"who''s bread", "It''s ok"}');
INSERT 0 1
如果输人的字符串中有括号"{"和"}"怎么办呢?只需把它们放到双引号中即可:
testdb=# insert into test77 values (5, '{"{os, dba}", "{dba, os}"}');
INSERT 0 1
如果输人的字符串中有双引号怎么办呢?这时需要在双引号前加反斜扛,如下所示:
testdb=# insert into test77 values(6,'{os\"dba}');
testdb=# select * from test77;
id | col1
----+-----------------------------------
1 | {how,howe,howl}
1 | {how,howe,howl}
3 | {"how many","how mach","how old"}
4 | {"who, what","CO.,LTD."}
3 | {"who's bread","It's ok"}
5 | {"{os, dba}","{dba, os}"}
6 | {"os\"dba"}
(7 行记录)
# ARRAY关键词的使用,需带单引号
testdb=# insert into test77 values(9, array['os', 'dba']);
INSERT 0 1
testdb=# insert into test77 values(9, array['os"win', 'dba']);
INSERT 0 1
testdb=# insert into test77 values(9, array['os''win', 'dba']);
INSERT 0 1
testdb=# select * from test77;
id | col1
----+-----------------------------------
1 | {how,howe,howl}
1 | {how,howe,howl}
3 | {"how many","how mach","how old"}
4 | {"who, what","CO.,LTD."}
3 | {"who's bread","It's ok"}
5 | {"{os, dba}","{dba, os}"}
6 | {"os\"dba"}
9 | {os,dba}
9 | {"os\"win",dba}
9 | {os'win,dba}
(10 行记录)
# 多维数组
testdb=# create table test779 (id int , col1 test[][]);
ERROR: type "test[]" does not exist
第1行create table test779 (id int , col1 test[][]);
testdb=# create table test779 (id int , col1 text[][]);
CREATE TABLE
testdb=# \d test779;
数据表 "public.test779"
栏位 | 类型 | Collation | Nullable | Default
------+---------+-----------+----------+---------
id | integer | | |
col1 | text[] | | |
testdb=# insert into test779 values(1, array[['aa'], ['cc']]);
INSERT 0 1
testdb=# insert into test779 values(1, array[['aa','bb'], ['cc','dd']]);
INSERT 0 1
testdb=# select * from test779;
id | col1
----+-------------------
1 | {{aa},{cc}}
1 | {{aa,bb},{cc,dd}}
(2 行记录)
testdb=# insert into test779 values(1, array[['aa','bb'], ['cc','dd','dd']]);
ERROR: multidimensional arrays must have array expressions with matching dimensions
testdb=# insert into test779 values(3, '{{aa, bb}, {cc, dd}}');
INSERT 0 1
testdb=# select * from test779;
id | col1
----+-------------------
1 | {{aa},{cc}}
1 | {{aa,bb},{cc,dd}}
3 | {{aa,bb},{cc,dd}}
(3 行记录)
# 默认情况下数组的下标是从1开始的,postgres的数组是可以指定开始下标的
testdb=# create table test7799 (id int[]);
CREATE TABLE
testdb=# insert into test7799 values('[2:4]={1,2,3}');
INSERT 0 1
testdb=# select id[2], id[3], id[4] from test7799;
id | id | id
----+----+----
1 | 2 | 3
(1 行记录)
testdb=# select id from test7799;
id
---------------
[2:4]={1,2,3}
(1 行记录)
testdb=# insert into test7799 values('{11,22,33}');
INSERT 0 1
testdb=# select id[2], id[3], id[4] from test7799;
id | id | id
----+----+----
1 | 2 | 3
22 | 33 |
(2 行记录)
testdb=# select id[1], id[2], id[3] from test7799;
id | id | id
----+----+----
| 1 | 2
11 | 22 | 33
(2 行记录)
# 从上面的例子可以看出,指定数组上下标的格式为:
`[下标:上标] = [元素值1, 元素值2, 元素值3..]`
testdb=# create table test666 (id int, col1 int[][]);
CREATE TABLE
testdb=# \d test666;
数据表 "public.test666"
栏位 | 类型 | Collation | Nullable | Default
------+-----------+-----------+----------+---------
id | integer | | |
col1 | integer[] | | |
testdb=# insert into test666 values(1, '{{1,2,3}, {4,5,6}, {7,8,9}}');
INSERT 0 1
testdb=# select * from test666;
id | col1
----+---------------------------
1 | {{1,2,3},{4,5,6},{7,8,9}}
(1 行记录)
# 多维数组读取
testdb=# select col1[1][1], col1[1][2], col1[2][1], col1[2][2] from test666;
col1 | col1 | col1 | col1
------+------+------+------
1 | 2 | 4 | 5
(1 行记录)
# 无法直接获取外层数组
testdb=# select id, col1[1] from test666;
id | col1
----+------
1 |
(1 行记录)
# 数组切换可获取
testdb=# select id, col1[1:1] from test666;
id | col1
----+-----------
1 | {{1,2,3}}
(1 行记录)
testdb=# select id, col1[1:2] from test666;
id | col1
----+-------------------
1 | {{1,2,3},{4,5,6}}
(1 行记录)
# 注意这里的外层其实是col1[3][1:2] == col1[1:3][1:2]
testdb=# select id, col1[3][1:2] from test666;
id | col1
----+---------------------
1 | {{1,2},{4,5},{7,8}}
(1 行记录)
testdb=# select id, col1[1:3][1:2] from test666;
id | col1
----+---------------------
1 | {{1,2},{4,5},{7,8}}
(1 行记录)
# 注意这里的外层其实是col1[1:2][2] == col1[1:2][1:2]
testdb=# select id, col1[1:2][2] from test666;
id | col1
----+---------------
1 | {{1,2},{4,5}}
(1 行记录)
testdb=# select id, col1[1:2][1:2] from test666;
id | col1
----+---------------
1 | {{1,2},{4,5}}
(1 行记录)
# 修改
# 可以修改整个字段数组值,或修改某一维度的单元素的值
# 不过无法直接修改某一维数组的值
testdb=# select * from test666;
id | col1
----+---------------------------
1 | {{1,2,3},{4,5,6},{7,8,9}}
(1 行记录)
testdb=# update test666 set col1[2][1] = 1000 where id=1;
UPDATE 1
testdb=# select * from test666;
id | col1
----+------------------------------
1 | {{1,2,3},{1000,5,6},{7,8,9}}
(1 行记录)
testdb=# update test666 set col1[2] = '{1,2,3}' where id=1;
ERROR: invalid input syntax for integer: "{1,2,3}"
第1行update test666 set col1[2] = '{1,2,3}' where id=1;
伪类类型
伪类型(Pseudo-Types)是PostgreSQL中不能作为字段的数据类型,但是它可以用于声明
一个函数的参数或者结果类型。所包含的类型有:
□ any:用于指示函数的输人参数可以是任意数据类型的。
□ anyelement:表示一个函数接受任何数据类型。
□ anyarray:表示一个函数接受任何数组类型。
□ anynonarray:表示一个函数接受任何非数组类塑。
□ anyenum:表示一个函数接受任何枚举类型_。
□ anyrange:表示一个函数接受任何范类型。
□ cstring:表示一个函数接受或返回一个空字符(0)结尾的C语言字符串。
□ internal:表示一个函数接受或者返冋一种服务器内部的数据类型。
□ language_handler:声明一个函数返回类型是pi语言的一个handler闲数。
□ fdw_handler:声明一个函数的返冋类型楚foreign-data wrapper的handler函数。
□ record:标识一个函数返回一个未详细定义各列的row类型。
□ trigger: 一个触发器函数要声明为返回trigger类型。
□ void:表示一个函数没有返问值。
□ opaque:已经过时的类型,旧的PostgreSQL版本中用于上面这些用途。
用C编写的函数(不管是内H的还是动态装载的)都可以卢明为接受或返冋上面任意一种伪数据类型。在把伪类型用作函数参数类型时,PostgreSQL数据库本身对类型检査就少了很多,保证类沏正确的任务就交给了写函数的幵发人员。
用过程语言编写的函数不一定都能使用上面列出的全部伪类型,具体能使用哪些需要丧看相关的过程语言文裆,或者查C•过程语言的实现。通常,过程语言都不支持使用“any”类型,但基本都能支持使用void和record作为结果类®,能支持多态闲数的过程语言还支持使
用“311)^〇^”、“311>^丨6咖111”、“3!1)^1111171”和‘‘311>010113〇'3>^’类型〇伪 类 型 “intemar用于声明那种只能在数据库系统内部调用的函数,它们不能直接在SQL査询里调用。如果函数至少有一个“internal”类型的参数,那么就不能从SQL里调用。
为了保留这个限制的类塑安全,一定要遵循这样的编码规则:对于没有任何一个"internal”参数的函数,不要把返回类型创建为“internal”。
其他类型
UUID
UUID( Universally Unique Identifiers)用于存储一个 UUID; UUID 定义在RFC 4122
和 ISO/IEC 9834-8:2005
中。它是一个128bit的数字
PostgreSQL核心源代码中没提供产生UUID的函数,contrib下的uuid-ossp模块提供UUID的函数
PG_LSN
pg_lsn类切是PostgrcSQL9.4版本之后提供的表示LSN ( Log Sequence Number)的一种数据类拟。LSN表示WALfi志的位酋。在一些记录WALti志信息的系统表中某些字段的类型就是pg_lsn类型
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。