上一篇文章整理并拓展了原书《PostgreSql11从入门到精通》第四章的内容,详细讲述了有关数据库表的创建、修改与删表
PostgreSQL11 | pgsql建表、改表与删表http://t.csdn.cn/P9OKA这一篇整理并拓展原书第五章(书第73页起)的内容。
数据类型和运算符
目录
PostgreSql数据类型介绍
PostgreSql支持多种数据类型,主要有整数类型、浮点数类型、任意精度数值、日期/时间类型、字符串类型、二进制类型、布尔类型和数组类型等。
如果看过上一篇文章的人,就会有印象,我们说过,当一个数据表的字段确定时,它自身的数据类型也就固定,当我们想要在已存数据的条件下修改字段的数据类型是需要谨慎存储范围的,那么本章就会介绍pgsql的所有的常用数据类型。
整数类型
整数型数据类型主要是用来存储数字。
在pgsql中,整形的类型有MALLINT、INT(INTEGER)和BIGINT
类型名称 | 说明 | 存储空间 |
---|---|---|
MALLINT | 小范围整数 | 2 字节 |
INT(INTEGER) | 普通大小的整数 | 4 字节 |
BIGINT | 大整数 | 8 字节 |
不同的整数类型存储所需的空间不一样,占用空间越大的类型所能存储的整数范围也越大。根据他们的存储空间也可以算出他们所能存储的整数范围,例如MALLINT类型,因为它的存储空间是2字节(1Byte<字节>=8bit,所以占16bit),所以所能存储的数的最大范围是(2^15)-1,即32767。
数据类型 | 取值范围 |
---|---|
SMALLINT | -32768到32767 |
INT(INTEGER) | -2147483648到2147483647 |
BIGINT | -9223372036854775808到9223372036854775807 |
我们可以创建一下表temp1,把三种类型的字段都创建并尝试向字段存储范围内与范围外的值查看结果。
create table temp1(x smallint,y int,z bigint);
在使用整形字段时注意取值范围。
浮点数类型
pgsql中使用浮点数类型来存储小数。
浮点类型有两种:REAL和DOUBLE PRECISION
类型名称 | 说明 | 存储需求 |
---|---|---|
REAL | 6 位十进制数字精度 | 4 字节 |
DOUBLE PRECISION | 15 位十进制数字精度 | 8 字节 |
数据类型 | 取值范围 | 精度 |
---|---|---|
REAL | 1E-37到1E+37 | 至少 6 位小数 |
DOUBLE PRECISION | 1E-307到1E+308 | 至少 15 位数字,太大或太小都会导致错误 |
pgsql也支持sql标准指示法float和float(p),用于声明非精确的数值类型。其中的“p”声明以二进制位表示的最低可接受精度。
REAL | float(1)到float(24) |
DOUBLE PRECISION | float(25)到float(53) |
在允许的范围之外将会报错,没有声明精度的float将默认为DOUBLE PRECISION类型。
可以通过下面展示的sql语句创建一个表来自行尝试数据添加的范围
create table temp2 (x float(5),y real,z double precision);
insert into temp2 () values();
任意精度类型
在pgsql中,使用NUMERIC(M, N)表示任意精度类型的数值。其中,M称为精度,即总共的位数,N称为标度,即小数的位数。
例如,563.186,精度为6,标度为3。
如果用户指定的精度超出精度外,就会进行四舍五入处理。
例如,创建表temp3
create table temp3 (x numeric(5,1),y numeric(5,1),z numeric(5,2));
insert into temp3 (x,y,z) values (9.14,9.15,7.15);
select * from temp3;
日期与时间类型
pgsql中有多种表示日期的数据类型,主要有TIME、DATE、TIMESTAMP。每一个类型都有合法的取值范围,当指定确实不合法的值时系统将“零”值插入数据库中。还有INTERVAL这种用于时间的快速加减计算的时间函数。
类型名称 | 含义 | 日期范围 | 存储需求 |
---|---|---|---|
TIME | 只用于一日内的时间 | 00:00:00~24:00:00 | 8 字节 |
DATE | 只用于日期 | 4713BC~5874897AD | 4 字节 |
TIMESTAMP | 日期和时间 | 4713BC~5874897AD | 8 字节 |
注意:因为格里高利历法里没有零年,所以数字上的1BC是公元零年。
另外,对于TIME和TIMESTAMP类型,默认情况下为without time zone(不带时区),如有需求可以设置为带时区(with time zone)。
1.TIME
time类型用于只需要时间信息的值,在存储时需要8字节,格式为HH:MM:SS。其中HH-小时,MM-分钟,SS-秒。time类型的取值为00:00:00~24:00:00。
例如,我们可以创建表temp4,并向建好的字段t中存入 10点23分46秒 和 19点37分。
create table temp4 (t time);
insert into temp4 (t) values ('10:23:46'),('19:37');
select * from temp4;
向表temp4中再插入值'101112'
insert into temp4 (t) values ('101112');
就是说,pgsql其实是可以识别整数通过系统日期函数转换成时间格式的数据
可以向time类型字段插入系统时间
例如,向表temp4中插入系统当前时间
先修改字段t的数据类型为不带时区的time类型
alter table temp4 alter column t type time without time zone;
删除表中数据
delete from temp4;
插入系统时间的两种方式
insert into temp4 values (current_time),(now());
select * from temp4;
2.DATE
date类型用在仅需要日期值时,没有时间部分,在存储时需要4字节,日期格式为'YYYY-MM-DD',其中YYYY表示年,MM表示月,DD表示天。
例如,创建表temp5为例
create table temp5 (d date);
向表中插入正确格式的数据
insert into temp5 values ('1998-08-08'),('19980808'),('20101010');
select * from temp5;
可以看到各个不同格式的日期都正确的插入到表中。
有关格式‘YYMMDD’的识别范围
当然,在给DATE类型的字段赋值的时候,可以使用字符串类型或者数字类型的数据插入,在使用格式‘YYMMDD’的整数识别的时候也是有临界值的,因为不知道世纪,所以pgsql规定以下规则解释两位年值。
范围区间 | 世纪取值 |
---|---|
00~69 | 2000~2069 |
70~99 | 1970~1999 |
为方便我们查看临界值效果,先将表清空。
delete from temp5;
向表中插入数据
insert into temp5 values ('691231'),('700101'),('000101'),('991231');
select * from temp5;
使用时间相关的函数
date类型数据还可以使用比如NOW()这样的时间函数来获取当前日期
先清理表中数据
delete from temp5;
insert into temp5 values (now());
select * from temp5;
NOW()函数返回日期和时间值,在保存到数据库时,只保存了其日期部分。
3.TIMESTAMP
TIMESTAMP的日期格式为YYYY-MM-DD HH:MM:SS。在存储的时候需要8字节,因此插入数据的时候需要保证在合法的取值区间内。
例如,创建表temp7,定义一个当前类型的字段ts并插入数据
create table temp7 (ts timestamp);
insert into temp7 values ('1991-12-25 19:38:00'),(now());
select * from temp7;
4.创建带时区的时间和时间类型
例如,创建表temp7h,并定义一个带时区的TIME类型字段t并插入数据
create table temp7th (t time with time zone);
PST (北美太平洋标准时间) 是UTC-8时区的知名名称之一,此时区位于格林威治向西8个时区,比UTC(协调世界时)落后8个小时与UTC的时间偏差可写为-08:00。
insert into temp7th values ('10:25:46 pst'),('10:25:46');
select * from temp7th;
5.通过时间函数INTERVAL快速加减时间
Interval 是另一种数据类型,用于存储和部署年,月,日,小时,分钟,秒,等中的时间。 月和日值是整数值,而秒的字段可以是分数值。
pgsql的间隔数据类型值占用16字节存储大小,这有助于存储可接受范围为- 178000000年至178000000 年的时间段。
我们可以依旧使用表temp7,但需要先清表后再插入一个时间
delete from temp7;
insert into temp7 values ('2000-10-01 10:30:20');
然后可以在查询时使用该函数来快速获得指定时间的加减计算的结果
select ts,ts-INTERVAL '6 months 2 hours 30 minutes' as "ts通过INTERVAL减去指定的时间" from temp7;
Interval的常用时间有:years、months、days、hours、minute、second
字符串类型
字符串类型用来存储字符串数据,除了可以存储字符串数据之外,还可以存储其他数据,比如图片和声音的二进制数据。
类型名称 | 说明 |
---|---|
CHAR(n) CHARACTER(n) | 固定长度非二进制字符串,不足补空白 |
VARCHAR(n) CHARACTER VARYING(N) | 变长非二进制字符串,有长度限制 |
TEXT | 变长非二进制字符串,无长度限制 |
1.CHARACTER(n)和CHARACTER VARYING(n)
其中的n是个正整数。当存储的字符串超出了n的范围时会产生一个错误,除非超过的部分是空白。
例如新建的表temp8
create table temp8 (
ch character(4),
vch character varying(4)
);
插入用于对比的字符串
insert into temp8 values ('ab','ab'),('abcd','abcd'),('ab ','ab ');
select concat('(',ch,')'),concat('(',vch,')') from temp8;
从查询结果来看,可以看到ch在保存‘ab'时在右侧填充空格以达到指定的长度,而vch字段仅仅保留了’ab'。
(上例中的concat()函数用于在查询时返回的结果为连接参数产生的字符串,与python中的字符串拼接输出控制台相似)
如果插入的字符长度完全超过规定的长度,例如插入’abcdefg‘,则报错
insert into temp8 values ('abcefg','abcefg');
2.TEXT类型
在pgsql中的text类型可以存储任何长度的字符串。尽管类型text不是sql标准,但许多其他数据库中也有该类型。
例如,创建表temp9,定义字段te,数据类型为text,向表中插入不同长度的字符串,sql语句如下。
create table temp9 (te text);
insert into temp9 values ('ab'),('abcd'),('ab ');
select concat('(',te,')') from temp9;
二进制类型
pgsql支持两类字符型数据,文本字符串和二进制字符。这里讲二进制数据的数据类型。
pgsql提供了BYTEA类型,用于存储二进制字符串。该类型存储空间为4字节+实际二进制字符串。
例如,创建表temp10
create table temp10(b bytea);
insert into temp10 values(E'\\000');
select * from temp10;
布尔类型
pgsql提供了Boolean布尔类型。布尔类型用1字节来存储,提供了TRUE(真)和FALSE(假)两个值。
另外,用户可以使用其他有效的文本值替代TRUE和FALSE。替代TRUE的文本值为’t'、'true'、'y'、'yes'和'1',替代FALSE的文本值为’f'、'false'、'n'、'no'和'0'。
例如,创建表temp11,定义bytea类型的字段b,向表中插入布尔型数据“TRUE”和“FALSE”。
create table temp11 (b boolean);
insert into temp11 values (TRUE),(FALSE),('y'),('no'),('0');
select * from temp11;
数组类型
pgsql允许将字段定义成定长或变长的一维或多维数组。
1.声明数组
在pgsql中,一个数组类型是通过在数组元素后附加方括号来命名的
例如:
numb int[]
xuehao text[][]
zuoye text[4][4]
这种格式与主流开发语言对于多维数组的定义格式类似,但方框中的整数为声明的数组的长度。
另外,对于一维的数组,也可以使用sql的标准声明。
pay_by_quarter int array[5];
2.插入数据
例如,创建表temp12
create table temp12(bt int[]);
insert into temp12 values('{{1,1,1},{2,2,2},{3,3,3}}');
select * from temp12;
如何选择数据类型
pgsql提供了大量的数据类型,为了优化储存、提高数据库性能,在任何情况下均应使用最准确的类型,即在所有可以表示该列值的类型中该类型所使用的存储空间最小。
1.整数与浮点数
如果不需要小数,就用整数来保存数据;如果需要小数,就使用浮点数类型。
对于浮点数,存入的数值会被该列定义的小数位进行四舍五入。例如,列值范围为1~99999,若使用整数,则int是最好的类型;若需要存储小数,则使用浮点数类型。
2.日期与时间类型
如果是需要记录时间,就使用time类型;如果只是需要记录日期,就使用DATE类型。
如果同时都需要记录,就可以使用TIMESTAMP类型。
3.CHAR和VARCHAR之间的特点和选择
CHAR和VARCHAR之间的区别就是,CHAR是固定长度字符,VARCHAR是可变的长度字符。
对于插入数据长度不够时,CHAR会自动填充插入数据的尾部空格,VARCHAR不会自动填充尾部空格。
常见运算符介绍
运算符连接表达式中的各个操作数,用来指明对操作数所进行的运算。
运算符概述
1.算术运算符
用于各类数值运算,包括加(+)、减(-)、乘(*)、除(/)和求余(%)
2.比较运算符
用于比较运算,包括大于(>)、小于(<)、等于(=)、大于等于(>=)、小于等于(<=)、不等于(!=)以及IN、BETWEEN...AND...、GREATEST、LEAST、LIKE等
3.逻辑运算符
逻辑运算符的求值所得结果均为t(TRUE)、f(FALSE)。这类运算符有逻辑非(NOT)、逻辑与(AND)和逻辑或(or)。
4.位操作运算符
参与位操作运算的操作数,按二进制位进行计算。位操作运算符包括与(&)、位或(|)、位非(~)、位异或(^)、左移(<<<)和右移(>>>) 共6种。
算数运算符
算数运算符是sql中最基本的运算符。
运算符 | 作用 |
---|---|
+ | 加法运算 |
- | 减法运算 |
* | 乘法运算 |
/ | 除法运算,返回商 |
% | 取余运算,返回余数 |
下面展示不同的算术运算符的使用
例如,创建表temp14
create table temp14 (num int);
insert into temp14 values (64);
select num,num+10,num-10,num+5-3,num+36.5 from temp14;
对temp14表中的num进行乘法、除法运算
select num,num*2,num/2,num/3,num%3 from temp14;
这里num/3,因为64无法被3整除,所以结果位21.3333保留四位小数,又因为整型的数据类型,结果保留为21
用0去除num
select num,num/0,num%0 from temp4;
在数学运算中,除数为0的运算是无意义的,因此除法中的除数不能为0。
比较运算符
一个比较运算符的结果总是t、f或是空值。
运算符 | 作用 |
---|---|
= | 等于 |
<> (!=) | 不等于 |
<= | 小于等于 |
>= | 大于等于 |
> | 大于 |
< | 小于 |
LEAST | 在有两个或多个参数时,返回最小值 |
GREATEST | 在有两个或多个参数时,返回最大值 |
BETWEEN...AND... | 判断一个值是否落在两个值之间 |
IN | 判断一个值是IN列表中的任意一个值 |
LIKE | 通配符匹配 |
下面展示不同比较运算符的使用方法
本例子中演示无需用到数据表,实际使用中按需求使用即可
1.等于运算符(=)
select 1=0,'2'=2,2=2,'b'='b',(1+3)=(2+1),null=null;
等于运算符在进行数值比较时有如下规则:
(1) 若有一个或两个参数为null,则比较运算的结果为空
(2) 若同一个比较运算中的两个参数都是字符串,则按照字符串进行比较
(3) 若两个参数均为整数,则按照整数进行比较
(4) 若一个字符串和数字进行相等判断,则pgsql可以将字符串转换为数字
2.不等于运算符(<> 或者 !=)
不等于运算符用于判断数字、字符串、表达式不相等的判断,如果不相等,返回t;否则返回f。
不等于运算符不能用于判断空值NULL。
select 'good'<>'god',1<>2,4!=4,5.5!=5,(1+3)!=(2+1),null<>null;
3.小于等于运算符(<=)
小于等于运算符用来判断左边的操作数是否小于或者等于右边的操作数。
如果小于或等于则返回值t,否则返回f。
小于等于不能用于判断空值
select 'good'<='god',1<=2,4<=4,5.5<=5,(1+3)<=(2+1),null<=null;
4.小于运算符(<)
小于运算符用来判断左边的操作数是否小于右边的操作数,如果小于,返回值为t,否则返回f。
小于运算符不能用于判断空值NULL
select 'good'<'god',1<2,4<4,5.5<5,(1+3)<(2+1),null<null;
5.大于等于运算符(>=)
大于等于运算符用于判断左边的操作数是否大于或等于右边的操作数,如果大于或者等于,则返回值为t,否则返回f。
大于等于运算符不能用于判断空值NULL。
select 'good'>='god',1>=2,4>=4,5.5>=5,(1+3)>=(2+1),null>=null;
6.大于运算符(>)
大于运算符用于判断左边的操作数是否大于右边的操作数,如果大于,返回值为1,否则返回0.
大于运算符不能用于判断空值NULL。
select 'good'>'god',1>2,4>4,5.5>5,(1+3)>(2+1),null>null;
7.BETWEEN...AND...运算符
BETWEEN...AND...运算符的语法格式为:
expr BETWEEN min AND max
所代表的意思是:假如 变量expr 大于或等于min 且 expr小于或等于max,则返回结果为t,否则为f。
所以该运算符的逻辑可以理解为“介于”,某变量是否在某区间范围内,与IN不同。
select 4 between 2 and 5,4 between 4 and 6,12 between 9 and 10;
同时也可以进行字符串的比较
select 'x' between 'f' and 'g','b' between 'a' and 'c','红' between '红' and '星';
(我们的数据库是默认的utf8编码,汉字的排序也遵循在码表中的顺序比较)
8.LEAST运算符
LEAST运算符的语法格式为:
LEAST(值1,值2, .... ,值n)
LEAST运算符在有2个及以上的多个参数中返回其中的最小值,若在其中有NULL值则忽略不参与比较。
select least(2,0),least(100,500,20);
9.GREATEST运算符
GREATEST运算符语法格式为:
GREATEST(值1,值2, .... ,值n)
GREATEST运算符在有2个及以上的多个参数中返回其中的最大值,若在其中有NULL值则忽略不参与比较。
select greatest(2,0),greatest(100,500,20);
10.IN、NOT IN运算符
IN运算符用来判断操作数是否为IN列表中的其中一个值,如果是,则返回t,否则返回f。
NOT IN运算符用来判断操作数是否为 NOT IN列表中的其中一个值,如果不是,则返回t,否则返回f。
(1) IN的使用
select 2 in (1,2,3,4) ,3 in (8,9,7);
(2) not in的使用
select 2 not in (1,2,3,4) ,3 not in (8,9,7);
通过结果可以看到,IN与NOT IN的返回值刚好相反,在左侧表达式为NULL,或者表中找不到匹配项,并且表中有一个表达式为NULL的情况下,IN的返回值均为空值。
select null in (1,2,3,4) ,10 not in (1,3,null);
11.LIKE运算符
LIKE运算符用于匹配字符串,语法为:
expr LIKE 匹配条件
如果变量expr 满足匹配条件,就返回t,否则返回f。
若expr或匹配条件中任何一个为NULL,则结果为空值。
匹配规则:
(1)‘%’,匹配任何数目的字符,甚至包括零字符
(2)‘_’,只能匹配一个字符
select 'stud' like 'stud','stud' like 'stu_','stud' like '%d','stud' like 't___','s' like null;
逻辑运算符
在sql中,所有逻辑运算符的求值所得结果均为TRUE、FALSE或空值。不同数据库中的表达方式相同。
运算符 | 作用 |
---|---|
NOT | 逻辑非 |
AND | 逻辑与 |
OR | 逻辑或 |
1.NOT
逻辑非运算符NOT表示当操作数为TRUE时,所得值为f;当操作数为FALSE时,所得值为t,当操作数为NULL时,所得返回值为空值。
select not '1',not 'y',not '0',not NULL,not 'n';
逻辑运算符的参数必须是布尔变量,如果随意输入其他类型的数值,就将会弹出错误提示信息。
2.AND
逻辑与运算符AND表示当所有操作数均为TRUE并且不为NULL时,计算所得结果为t,当一个或多个操作数为FALSE时,所得结果为f,其余情况返回空值。
select '1' and 'y','1' and '0','1' and NULL,'0' and NULL;
“AND”运算符可以有多个操作数,但要注意:多个操作数运算时,AND两边一定要使用空格键隔开,不然会影响结果的正确性。
3.OR
逻辑或运算符OR表示当两个操作数均为非NULL值时,任意一个操作数为TRUE,则结果为t,否则结果为f;有一个操作数为NULL时,若另一个操作数为TRUE,则结果为t,否则结果为空值;当两个操作数均为NULL时,所得结果为空值。
select '1' or 't' or '0','1' or 'y','1' or NULL,'0' or NULL,NULL or NULL;
运算符的优先级
运算的优先级决定了不同的运算符在表达式中计算的先后顺序。
优先级 | 运算符 |
---|---|
最低 | =(赋值运算),:= |
| OR | |
AND | |
NOT | |
BETWEEN,CASE,WHEN,THEN,ELSE | |
=(比较运算),>=,>,<=,<,<>,!=,IS,LIKE,IN | |
-(减法运算),+ | |
*,/(除法运算),%(取余运算) | |
-(负号符) | |
最高 | ! |
结合案例——运算符的使用
案例目的:创建数据表,并对表中的数据进行运算操作,掌握各种运算符的使用方法。
创建表temp15,其中包含VARCHAR类型的字段note和INT类型的字段price,使用运算符对表temp15中不同的字段进行运算;使用逻辑操作符对数据进行逻辑操作。
1.创建表temp15
create table temp15 (note varchar(100),price INT);
2.向表中插入一条记录,note值为“Redstar”,price值为50
insert into temp15 values ('Redstar',50);
3.对temp15表中的整数值字段price进行算数运算
select price,price+10,price-10,price*2,price/2,price%3 from temp15;
4.对temp15中的整型数值字段price进行比较运算
select price,price>10,price<10,price!=10,price=10,price<>10 from temp15;
5.判断price值是否落在30~80之间,返回与70,30相比最大的值,判断是否为IN列表(10,20,50,35)中的某个值
select price,price between 30 and 80,greatest(price,70,30),price in(10,20,50,35) from temp15;
6.对temp15中的字符串数值字段note进行比较运算,判断表temp15中note字段是否为空;使用LIKE判断是否以字母’t‘开头,是否以’r'结尾。
select note,note is NULL,note LIKE 't%',note LIKE '%r' from temp15;
作者的话(Alvin):
本文根据原书《PostgreSql11 从入门到精通》(清华大学出版社)第5章总结整理,为提问与解答可以帮助更多人,本博客模拟GitHub的issue方案,所以私信已关,有问题请在评论区直接指正与提问,允许转发、复制或引用本文章,必须遵守开源法则注释来源与作者,感谢您的阅读。