PostgreSQL数据类型
PostgreSQL支持最大字段大小为1GB
数字类型
类型名称 | 存储长度 | 描述 | 范围 |
---|---|---|---|
smallint | 2字节 | 小范围整数类型 | -32768到+32767 |
integer | 4字节 | 整数类型 | -2 147 483 648到+2 147 483 647 |
bigint | 8字节 | 大范围整数类型 | -9 223 372 036 854 775 808到+9 223 372 036 854 775 807 |
decimal | 可变 | 用户指定精度 | 小数点前131 072位;小数点后16 383位 |
numeric | 可变 | 用户指定精度 | 小数点前131 072位;小数点后16 383位 |
real | 4字节 | 变长,不精确 | 6位十进制精度 |
doblue precision | 8字节 | 变长,不精确 | 15位十进制精度 |
smallserial | 2字节 | smallint自增序列 | 1到+32767 |
serial | 4字节 | integer自增序列 | 1到+2 147 483 647 |
bigserial | 8字节 | bigint自增序列 | 1到+9 223 372 036 854 775 807 |
从性能上考虑不建议使用numeric数据类型
# 创建表
CREATE TABLE test_serial(id serial,flag text);
# 插入数据
INSERT INTO test_serial(flag)VALUES('a');
- 数字类型操作符和数字函数
SELECT 1+2,2*3,4/2,8%3;
# 按模取余
SELECT mod(8,3);
# 四舍五入
SELECT round(10.2),round(10.9);
# 返回大于或等于给出参数的最小整数
SELECT ceil(3.6),ceil(-3.6);
# 返回小于或等于给出参数的最小整数
SELECT floor(3.6),floor(-3.6);
字符类型
字符类型名称 | 描述 |
---|---|
varcher(n),character varying(n) | 变长,自负最大数有限制 |
char(n),character(n) | 定长,字符数没达到 |
text | 变长,无长度限制 |
# 创建表
CREATE TABLE test_char(col1 varchar(4),col2 character(4));
# 插入数据
INSERT INTO test_char(col1,col2)VALUES('a','a');
# 查询字符串字符数
SELECT char_length(col1),char_length(col2) FROM test_char;
# 查看字段实际占用的物理空间大小(字符串占用的字符数)
SELECT octet_length(col1),octet_length(col2) FROM test_char;
- 字符类型函数
# 计算字符串中的字符数
SELECT char_length('abcd');
# 计算字符串占用字节数
SELECT octet_length('abcd');
# 指定字符在字符串中的位置
SELECT position('ab'in 'abcd');
# 提取字符串中的子串
SELECT substring('francs' from 3 for 4);
# 拆分字符串
split_part(string text,delimiter text,field int)
SELECT split_part('abc@def1@nb','@',2); # return def1
时间/日期类型
字符类型名称 | 存储长度 | 描述 |
---|---|---|
timestamp[§] [without time zone] | 8字节 | 包括日期和时间,不带时区,简写成timestamp |
timestamp[§] [with time zone] | 8字节 | 包括日期和时间,带时区,简写成timestampz |
date | 4字节 | 日期,但不包括一天中的时间 |
time[§] [without time zone] | 8字节 | 一天中的时间,不包含日期,不带时区 |
time[§] [with time zone] | 12字节 | 一天中的时间,不包含日期,带时区 |
interval[fields] [§] | 16字节 | 时间间隔 |
# 显示系统当前时间
SELECT now();
# 转换成date格式
SELECT now()::date;
# 转换成time with time zone
SELECT now()::time with time zone;
# interval 指时间间隔,时间间隔单位可以是hour、day、month、year等
SELECT now(),now()+interval'1 day';
时间类型中的§是指时间精度,具体指秒后面小数点保留的位数,如果没有声明精度默认为6
# 精度设置为0
SELECT now(),now()::timestamp(0);
- 时间/日期类型操作符
# 日期相加
SELECT date '2017-07-29'+interval'1 day';
# 日期相减
SELECT date '2017-07-29'-interval'1 hour';
# 日期相乘
SELECT 100* interval '1 second';
# 日期相除
SELECT interval '1 hour' / double precision '3';
- 时间/日期类型常用函数
# 显示当前时间
SELECT current_date, current_time;
EXTRACT函数,可以从日期、时间数据类型中抽取年、月、日、时、分、秒信息
EXTRACT(field FROM source)
field值可以为century、year、month、day、hour、miniute、second等,source 类型为timestamp、time、interval的值表达式
# 取年份SELECT EXTRACT(year FROM now());# 取小时、分钟SELECT EXTRACT(hour FROM now()),EXTRACT(minute FROM now());#取秒SELECT EXTRACT(second FROM now());# 取当前日期所在年份中的第几周SELECT EXTRACT(week FROM now());# 当天属于当年的第几天SELECT EXTRACT(doy FROM now());# 当天属于当月的第几天SELECT EXTRACT(day FROM now());
布尔类型
字符类型名称 | 存储长度 | 描述 |
---|---|---|
boolean | 1字节 | 状态为true或false |
true状态的有效值可以TRUE、t、true、y、yes、on、1;
false状态的有效值为FALISE、f、false、n、no、off、0;
可以插入NULL值
网络地址类型
字符类型名称 | 存储长度 | 描述 |
---|---|---|
cidr | 7或19字节 | IPv4和IPv6网络 |
inet | 7或19字节 | IPv4和IPv6网络 |
macaddr | 6字节 | MAC地址 |
Macaddr8 | 8字节 | MAC地址(EUI-64格式) |
SELECT '192.168.1.100'::cidr;SELECT '192.168.1.100/32'::inet;
cidr类型对IP地址和子网掩码合法性进行检查,而inet不会;
cidr比inet网络类型更严谨;
- 网络地址操作符
操作符 | 描述 | 举例 |
---|---|---|
< | 小于 | inet ‘192.168.1.5’ < inet ‘192.168.1.6’ |
<= | 小于等于 | inet ‘192.168.1.5’ <= inet ‘192.168.1.5’ |
= | 等于 | inet ‘192.168.1.5’ = inet’192. 168.1.5’ |
>= | 大于等于 | inet ‘192.168.1.5’>= inet’192.168.1.5’ |
> | 大于 | inet ‘192.168.1.5’> inet ‘192.168.1.4’ |
<> | 不等于 | inet ‘192.168.1.5’<> inet ‘192.168.1.4’ |
<< | 被包含 | inet ‘192.168.1.5’ << inet ‘192.168.1/24’ |
<<= | 被包含或等于 | inet ‘192.168.1/24’ <<= inet ‘192.168.1/24’ |
>> | 包含 | inet ‘192.168.1/24’>> inet ‘192.168.1.5’ |
>>= | 包含或等于 | inet ‘192.168.1/24’>>= inet ‘192.168.1/24’ |
&& | 包含或被包含 | inet ‘192.168.1/24’ && inet ‘192.168.1.80/28’ |
~ | 按位取反 | ~ inet ‘192.168.1.6’ |
& | 按位与 | inet ‘192.168.1.6’ & inet ‘0.0.0.255’ |
| | 按位或 | inet ‘192.168.1.6’ I inet ‘0.0.0.255’ |
+ | 加 | inet ‘192.168.1.6’ + 25 |
- | 减 | inet ‘192.168.1.43’ - 36 |
- | 减 | inet ‘192.168.1.43’ - inet ‘192. 168.1.19’ |
- 网络地址函数
# 取IP地址,返回文本格式SELECT host(cidr '192.168.1.0/24');# 去IP地址和网络掩码,返回文本格式SELECT text(cidr '192.168.1.0/24');# 取网络地址子网掩码,返回文本格式SELECT netwask(cidr )
数组类型
创建表时在字段数据类型后面加方括号“[]”
# 创建表CREATE TABLE test_array1( id integer, array_i integer[], array_t text[]);# 插入数据INSERT INTO test_array1(id,array_i,array_t)VALUES(1,'{1,2,3}','{"a","b","c"}');INSERT INTO test_array1(id,array_i,array_t)VALUES(2,array[1,2,3],array['d','e','f']);# 查询数据SELECT * FROM test_array1;
- 查询数组元素
# 查询数组全部元素值SELECT array_i FROM test_array1 WHERE id=1;# 数组引用通过方括号“[]”方式,数组下标写在方括号内,编号范围为1到nSELECT array_i[1],array_[3] FROM test_array1 WHERE id=1;
- 数组元素的追加、删除、更新操作
# 向数组末端追加一个元素SELECT array_append(array[1,2,3],4);SELECT array[1,2,3] || 4;# 数组元素删除,删除全部的2SELECT array[1,2,3,4],array_remove(array[1,2,2,4],2);# 数组元素修改UPDATE test_array1 SET array_i[3]=4 WHERE id=1;UPDATE test_array1 SET array_i=array[7,8,9] WHERE id=1;
- 数组操作符
操作符 | 描述 | 举例 | 结果 |
---|---|---|---|
= | 等于 | ARRAYI1.1,2.1.31]:int[] = ARRAY[1,2,3] | t |
<> | 不等于 | ARRAY[1,2,3] <> ARRAY[1,2,4] | t |
< | 小于 | ARRAY[1,2,3]< ARRAY[1,2,4] | t |
> | 大于 | ARRAY[1,4,3]> ARRAY[1,2,4] | t |
<= | 小于等于 | ARRAY[1,2,3] <= ARRAY[1,2,3] | t |
>= | 大于等于 | ARRAY[1,4,3]>= ARRAY[1,4,3] | t |
@> | 包含 | ARRAY[1,4,3] @> ARRAY[3,1] | t |
<@ | 被包含 | ARRAY[2,7] <@ ARRAY[1,7,4,2,6] | t |
&& | 重叠(具有公共元素) | ARRAY[1,4,3] && ARRAY[2,1] | t |
|| | 数组和数组串接 | ARRAY[1,2,3]II ARRAY[4,5,6] | {1,2,3,4,5,6} |
|| | 数组和数组串接 | ARRAY[1,2,3] II ARRAY[[4,5,6],[7,8,9]] | {1,2,3},{4,5,6},{7,8,9}} |
|| | 元素和数组串接 | 3 II ARRAY[4,5,6] | {3,4,5,6} |
|| | 数组和元素串接 | ARRAY[4,5,6] II 7 | {4,5,6,7} |
- 数组函数
# 添加元素或删除元素SELECT array_append(array[1,2],3),array_remove(array[1,2],2);# 获取数组维度SELECT array_ndims(array[1,2]);# 获取数组长度SELECT array_length(array[1,2],1);# 返回数组中某一个数组元素第一次出现的位置SELECT array_position(array['a','b','c','d'],'d');# 数组元素替换SELECT array_replace(array[1,2,5,4],5,10);# 将数组元素输出到字符串SELECT array_to_string(array[1,2,null,3],',','10');
范围类型
字符类型名称 | 描述 |
---|---|
int4range | integer范围类型 |
int8range | bigint范围类型 |
numranage | numeric范围类型 |
tsrange | 不带时区的timestamp范围类型 |
tstzranage | 带时区的timestamp范围类型 |
daterange | date范围类型 |
# [1,5)SELECT int4ranage(1,5);# [2017-07-01,2017-07-30)SELECT daterange('2017-07-01','2017-07-30');# 指定上下边界[1,4)SELECT int4range(1,3,'[]');
范围类型标准的边界模式,即下界包含同时上界排除
- 范围类型操作符
# 包含元素操作符SELECT int4ranage(4,7) @>4;# 包含范围操作符SELECT int4range(4,7) int4range(4,6);# 等于操作符SELECT int4range(4,7)=int4range(4,6,'[]');
- 范围类型函数
# 取范围下界SELECT lower(int4range(1,10));# 取范围上界SELECT upper(int4range(1,10));# 范围是否为空SELECT isempty(int4range(1,10));
- 给范围类型创建索引
范围类型数据支持创建GiST索引,GiST索引支持的操作符有“=”、“&&”、“<@”、“@>”、“<<”、“>>”、“-|-”、“&<”、“&>”等
CREATE INDEX idx_ip_address_range ON ip_address USING gist(ip_range);
json/jsonb类型
SELECT '{"a":1,"b":2}'::json;# 创建表CREATE TABLE test_json1 (id serial primary key,name json);# 插入数据INSERT INTO test_json1(name)VALUES('{"col1":1,"col2":"francs","col3":"male"}');INSERT INTO test_json1(name)VALUES('{"col1":1,"col2":"fp","col3":"female"}');# 查询数据SELECT * FROM test_json1;
- 查询json数据
# 查询json数据的键值SELECT name -> 'col2' FROM test_json1 WHERE id=1;# 以文本格式返回json字段键值SELECT name ->> 'col2' FROM test_json1 WHERE id=1;
- jsonb与json差异
json存储格式为文本,jsonb存储格式为二进制;
json写入比jsonb快,但检索比jsonb慢;
json输出的键的顺序和输入不一样,json的输出键的顺序和输入完全一样;
jsonb类型会去掉输入数据中键值的空格;
jsonb会删除重复的键,仅保留最后一个;
SELECT '{"bar":"baz","balance":7.77,"active":false}'::jsonb;
- jsonb与json操作符
# 以文本格式返回json字段键值SELECT name ->> 'col2' FROM test_json1 WHERE id=1;# 字符串是否作为顶层值SELECT '{"a":1,"b":2}'::jsonb ? 'a';# 删除json数据的键/值SELECT '{"a":1,"b":2}'::jsonb - 'a';
- jsonb与json函数
# 扩展最外层的json对象成为一组键/值结果集SELECT * FROM json_each('{"a":"foo","b":"bar"}');# 以文本形式返回结果SELECT * FROM json_each_text('{"a":"foo","b":"bar"}');# 将行作为json对象返回SELECT row_to_json(test_copy)FROM test_copy WHERE id=1;# 返回最外层的json对象中的键的集合SELECT * FROM json_object_keys('{"a":"foo","b":"bar"}');
- jsonb键/值的追加、删除、更新
# 增减sex键/值SELECT '{"name":"francs","age":"31"}'::jsonb||'{"sex":"male"}'::jsonb;# 删除键/值SELECT '{"name":"James","email":"james@localhost"}'::jsonb - 'email';# 删除嵌套contact中fax键/值SELECT '{"name":"James","contact":{"phone":"01234 567890","fax":"01987 543210"}}'::jsonb #- '{contact,fax}'::text[];# 删除嵌套aliases中的位置为1的键/值SELECT '{"name":"James","aliases":["Jamie","The Jamester","J Man"]}'::jsonb #- '{aliases,1}'::text[];# 键/值更新SELECT '{"name":"francs","age":"31"}'::jsonb || '{"age":"32"}'::jsonb;SELECT jsonb_set('{"name":"francs","age":"31"}'::jsonb,'{age}','"32"'::jsonb,false);SELECT jsonb_set('{"name":"francs","age":"31"}'::jsonb,'{sex}','"male"'::jsonb,true);
数据类型转换
PostgreSQL数据类型转换主要有三种方式:通过格式化函数、CAST函数、::操作服务
- 通过格式函数进行转换
函数 | 返回类型 | 描述 | 实例 |
---|---|---|---|
to_char(timestamp,text) | text | 把时间戳转换为字符串 | to_char(current_timestamp,‘HH12:MI:SS’) |
to_char(interval,text) | text | 把间隔转换成字符串 | to_char(interval ‘15h 2m 12s’,‘HH24:MI:SS’) |
to_char(int,text) | text | 把整数转换成字符串 | to_char(125,‘999’) |
to_char(numeric,text) | text | 把数字转换成字符串 | to_char(-125.8,‘999D99S’) |
to_date(text,text) | date | 把字符串转换成日期 | to_date(‘05 Dec 2000’,‘DD Mon YYYY’) |
to_number(text,text) | numeric | 把字符串转换成数字 | to_number(‘12,454.8-’,‘99G999D9s’) |
to_timestamp(text,text) | timestamp with time zone | 把字符串转换成时间戳 | to_timestamp(‘05 Dec 2000’,‘DD Mon YYYY’) |
- 通过CAST函数进行转换
# 将varchar转换成textSELECT CAST(varchar'123' as text);# 将varchar转换成int4SELECT CAST(varchar'123' as int4);
- 通过::操作符进行转换
SELECT 1::int4, 3/2::numeric;SELECT oid,relname FROM pg_class WHERE relname='test_json1';SELECT attname FROM pg_attribute WHERE attrelid='16509' AND attnum >0;SELECT attname FROM pg_attribute WHERE attrelid='test_json1'::regclass AND attnum >0;