PostgreSQL学习笔记(上)
1、基础知识
SQL语言包含4个部分:
数据定义语言(DDL):DROP
、CREATE
、ALTER
等语句。
数据操作语言(DML):INSERT
(插入)、UPDATE
(修改)、DELETE
(删除)语句。
数据查询语言(DQL):SELECT
语句。
数据控制语言(DCL):GRANT
、REVOKE
、COMMIT
、ROLLBACK
等语句。
2、数据库的基本操作
2.1 创建数据库
# 创建数据库
create database sample_db;
2.2 修改数据库
# 语法
ALTER DATABASE name [ [WITH] option [...] ]
# 修改拥有者
ALTER DATABASE sample_db OWNER TO pg_database_owner;
# 修改名字
ALTER DATABASE sample_db RENAME TO sample_db_alter;
# 修改数据库的连接最大值为10
ALTER DATABASE sample_db WITH CONNECTION LIMIT=10;
2.3 删除数据库
# 语法
DROP DATABASE database_name[,...n];
# 删除数据库
DROP DATABASE sample_db;
并不是所有数据库在任何时候都可以被删除,只有处于正常状态下的数据库,才能使用DROP
语句删除。当数据库
处于以下状态时不能被删除:数据库正在使用;数据库正在恢复;数据库包含用于复制的对象。
2.4 关闭数据库
先找到指定数据库的pid:
SELECT datname,pid FROM pg_stat_activity;
关闭数据库连接:
SELECT pg_terminate_backend(14788);
其实可以一步完成:
SELECT CAST(pg_terminate_backend(pid) AS VARCHAR(10)) FROM pg_stat_activity WHERE datname='sample_db';
3、数据表的基本操作
3.1 创建数据表
# 语法
CREATE TABLE <表名>
(
字段名1 数据类型 [列级别约束条件] [默认值],
字段名2 数据类型 [列级别约束条件] [默认值],
...
[表级别约束条件]
);
使用CREATE TABLE
创建表时,必须指定以下信息:
-
要创建的表的名称不区分大小写,不能使用SQL语言中的关键字,如DROP、ALTER、INSERT等。
-
数据表中如果创建多个列,每一个列(字段)的名称和数据类型都要用逗号隔开。
# 创建表
CREATE TABLE tb_emp1
(
id INT,
name VARCHAR(25),
deptId INT,
salary FLOAT
);
3.1.1 使用主键约束
1、单字段主键
定义列的同时使用主键:
# 语法
字段名 数据类型 PRIMARY KEY
CREATE TABLE tb_emp2
(
id INT PRIMARY KEY,
name VARCHAR(25),
deptId INT,
salary FLOAT
);
在定义完所有列之后使用主键:
# 语法
[CONSTRAINT<约束名>] PRIMARY KEY [字段名]
CREATE TABLE tb_emp3
(
id INT,
name VARCHAR(25),
deptId INT,
salary FLOAT,
PRIMARY KEY(id)
);
2、多字段联合主键
# 语法
PRIMARY KEY[字段1,字段2,···,字段n]
CREATE TABLE tb_emp4
(
name VARCHAR(25),
deptId INT,
salary FLOAT,
PRIMARY KEY(name,deptId)
);
3.1.2 使用外键约束
# 语法
[CONSTRAINT <外键名>] FOREIN KEY 字段名1 [,字段名2,···]
REFERENCES <主表名> 主键列1 [,主键列2,···】
CREATE TABLE tb_dept1
(
id INT PRIMARY KEY,
name VARCHAR(22) NOT NULL,
location VARCHAR(50)
);
CREATE TABLE tb_emp5
(
id INT PRIMARY KEY,
name VARCHAR(25),
deptId INT,
salary FLOAT,
CONSTRAINT fk_emp_deptl FOREIGN KEY(deptId) REFERENCES tb_dept1(id)
);
3.1.3 使用非空约束
# 语法
字段名 数据类型 NOT NULL
CREATE TABLE tb_emp6
(
id INT PRIMARY KEY,
name VARCHAR(25) NOT NULL,
deptId INT,
salary FLOAT,
CONSTRAINT fk_emp_dept2 FOREIGN KEY(deptId) REFERENCES tb_dept1(id)
);
3.1.4 使用唯一性约束
1、在定义完列之后使用
# 语法
字段名 数据类型 UNIQUE
CREATE TABLE tb_dept2
(
id INT PRIMARY KEY,
name VARCHAR(22) UNIQUE,
location VARCHAR(50)
);
2、在定义完所有列之后指定唯一约束
# 语法
[CONSTRAINT<约束名>]UNIQUE(<字段名>)
CREATE TABLE tb_dept3
(
id INT PRIMARY KEY,
name VARCHAR(22),
location VARCHAR(50),
CONSTRAINT STH UNIQUE(name)
);
UNIQUE
和PRIMARY KEY
的区别:一个表中可以有多个字段声明为UNIQUE,但只能有一个PRIMARY KEY 声明;
声明为PRIMAY KEY 的列不允许有空值,但是声明为UNIQUE 的字段允许空值(NULL)的存在。
3.1.5 使用默认约束
# 语法
字段名 数据类型 DEFAULT 默认值
CREATE TABLE tb_emp7
(
id INT PRIMARY KEY,
name VARCHAR(25)NOT NULL,
deptId INT DEFAULT 1111,
salary FLOAT,
CONSTRAINT fk_emp_dept3 FOREIGN KEY(deptId) REFERENCES tb_dept1(id)
);
3.2 修改表数据
3.2.1 修改表名
# 语法
ALTER TABLE<旧表名>RENAME TO<新表名>;
ALTER TABLE tb_dept3 RENAME TO tbdepartment3;
3.2.2 修改字段的数据类型
# 语法
ALTER TABLE<表名> ALTER COLUMN <字段名> TYPE <数据类型>
ALTER TABLE tb_dept1 ALTER COLUMN name TYPE VARCHAR(30);
3.2.3 修改字段名
# 语法
ALTER TABLE <表名> RENAME <旧字段名> TO <新字段名> <新数据类型>;
ALTER TABLE tb_dept1 RENAME location TO loc;
3.2.4 添加字段
# 语法
ALTER TABLE <表名> ADD COLUMN <新字段名> <数据类型>
1、添加无完整约束条件的字段
ALTER TABLE tb_dept1 ADD COLUMN managerId INT;
2、添加有完整约束条件的字段
ALTER TABLE tb_dept1 ADD COLUMN column1 VARCHAR(12) NOT NULL;
3.2.5 删除字段
# 语法
ALTER TABLE<表名>DROP<字段名>;
ALTER TABLE tb_dept1 DROP column1;
3.2.6 删除表的外键约束
# 语法
ALTER TABLE<表名> DROP CONSTRAINT <外键约束名>
CREATE TABLE tb_emp9
(
id INT PRIMARY KEY,
name VARCHAR(25),
deptId INT,
salary FLOAT,
CONSTRAINT fk_emp_dept FOREIGN KEY(deptId) REFERENCES tb_dept1(id)
);
ALTER TABLE tb_emp9 DROP CONSTRAINT fk_emp_dept;
3.2.7 修改约束
ALTER TABLE tb_emp9 ALTER COLUMN name SET NOT NULL;
4.3 删除数据表
4.3.1 删除没有被关联的表
# 语法
DROP TABLE[IF EXISTS]表1,表2,表n;
DROP TABLE IF EXISTS tb_dept2;
4.3.2 删除被其它表关联的主表
CREATE TABLE tb_dept2
(
id INT PRIMARY KEY,
name VARCHAR(22),
location VARCHAR(50)
);
CREATE TABLE tb_emp
(
id INT PRIMARY KEY,
name VARCHAR(25),
deptId INT,
salary FLOAT,
CONSTRAINT fk_emp_dept FOREIGN KEY(deptId) REFERENCES tb_dept2(id)
);
# 有关联无法删除
DROP TABLE IF EXISTS tb_dept2;
ALTER TABLE tb_emp DROP CONSTRAINT fk_emp_dept;
DROP TABLE tb_dept2;
4、数据类型和运算符
4.1 数据类型介绍
4.1.1 整数类型
PostgreSQL 主要提供的整数类型有 SMALLINT
、INT(INTEGER)
和BIGINT
。
类型名称 | 说明 | 存储需求 | 存储范围 |
---|---|---|---|
SMALLINT |
小范围的整数 | 2个字节 | -2^15~2^15-1 |
INT(INTEGER) |
普通大小的整数 | 4个字节 | -2^31~2^31-1 |
BIGINT |
大整数 | 8个字节 | -2^63~2^63-1 |
CREATE TABLE tmp1(X SMALLINT,y INT,z BIGINT );
4.1.2 浮点数类型
PostgreSQL 中使用浮点数来表示小数。浮点类型有两种:REAL
和 DOUBLE PRECISION
。
类型名称 | 说明 | 存储需求 | 存储范围 | 精度 |
---|---|---|---|---|
REAL |
6位十进制数字精度 | 4 个字节 | 1E-37~1E+37 |
至少6位 |
DOUBLE PRECISION |
15 位十进制数字精度 | 8个字节 | 1E-307~1E+308 |
至少15位 |
PostgreSQL 也支持SQL 标准表示法,float
和 float(p)
用于声明非精确的数值类型。其中,p声明以二进制位
表示的最低可接受精度。在选取 REAL
类型的时候,PostgreSQL 接受 float(1)
到float(24)
,在选取
DOUBLE PRECISION
的时候,接受float(25)
到float(53)
。在允许范围之外的p值将导致一个错误,没有声明精
度的 float 将被当作 DOUBLE PRECISION
。
CREATE TABLE tmp2(x FLOAT(5),y REAL,z DOUBLE PRECISION);
在 PostgreSQL中,浮点类型有几个特殊值。其中,Infinity
表示正无穷大,-Infinity
表示负无穷大,NaN
表示不是一个数字。
4.1.3 任意精度类型
在PostgreSQL中,NUMERIC
表示数值是任意精度的类型,使用 NUMERIC (M,N)
来表示。其中,M称为精度,表
示总的位数;N称为标度,表示小数的位数。例如563.186中,精度为6,标度为3。
NUMERIC的有效的取值范围由M和N的值决定。如果改变M而固定N,则其取值范围将随M的变大而变大。另外如
果用户数据的精度超出指定精度,则会四舍五入进行处理。
CREATE TABLE tmp3(x NUMERIC(5,1),y NUMERIC(5,2));
INSERT INTO tmp3 VALUES(9.12,9.15);
SELECT * FROM tmp3;
x |y |
---+----+
9.1|9.15|
4.1.4 日期与时间类型
PostgreSQL 中有多种表示日期的数据类型,主要有:TIME
、DATE
、TIMESTAMP
和INTERVAL
。每一个类型都有
合法的取值范围,当指定确实不合法的值时,系统将“零”值插入到数据库中。
类型名称 | 含义 | 存储需求 |
---|---|---|
TIME |
只用于一日内时间 | 8字节 |
DATE |
只用于日期 | 4字节 |
TIMESTAMP |
日期和时间 | 8字节 |
另外,对于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
。
CREATE TABLE tmp4(t TIME);
INSERT INTO tmp4 values('10:05:05'),('23:23');
SELECT * FROM tmp4;
t |
--------+
10:05:05|
23:23:00|
INSERT INTO tmp4 values('101112');
SELECT*FROM tmp4;
t |
--------+
10:05:05|
23:23:00|
10:11:12|
ALTER TABLE tmp4 ALTER COLUMN t TYPE time without time zone;
DELETE FROM tmp4;
INSERT INTO tmp4 values(CURRENT_TIME),(NOW());
SELECT * FROM tmp4;
t |
--------+
15:39:11|
15:39:11|
2、Date
DATE 类型用在仅需要日期值时,没有时间部分,在存储时需要4 个字节,日期格式为YYYY-MM-DD
。其中,YYYY
表示年;MM 表示月;DD表示日。在给 DATE 类型的字段赋值时,可以使用字符串类型或者数字类型的数据插
入,只要符合DATE 的日期格式即可,具体如下:
-
以
YYYY-MM-DD
或者YYYYMMDD
字符串格式表示的日期。例如输入2012-12-31
或者20121231
,插入数据库的日期都为
2012-12-31
。 -
以
YY-MM-DD
或者YYMMDD
字符串格式表示的日期,在这里,YY表示两位的年值。包含两位年值的日期会令人模糊,因为不知道世纪。PostgreSQL 使用以下规则解释两位年值:
00~69
范围的年值转换为2000~2069
;70~99
范围的年值转换为1970~1999
。例如输入12-12-31
,插入数据库的日期为2012-12-31
;输入981231
,插入数据的日期为1998-12-31
。 -
使用 CURRENT DATE或者 NOWO插入当前系统日期。
CREATE TABLE tmp5(d DATE);
INSERT INTO tmp5 values('1998-08-08'),('19980808'),('20101010');
SELECT * FROM tmp5;
d |
----------+
1998-08-08|
1998-08-08|
2010-10-10|
DELETE FROM tmp5;
INSERT INTO tmp5 values('99-09-09'),('990909'),('000101'),('121212');
SELECT * FROM tmp5;
d |
----------+
1999-09-09|
1999-09-09|
2000-01-01|
2012-12-12|
DELETE FROM tmp5;
INSERT INTO tmp5 values(NOW());
SELECT * FROM tmp5;
d |
----------+
2022-09-11|
NOWO函数返回日期和时间值,在保存到数据库时,只保留了其日期部分。
3、TIMESTAMP
TIMESTAMP的日期格式为YYYY-MM-DD HH:MM:SS
。在存储时需要8个字节,因此在插入数据时,要保证在合法的
取值范围内。
CREATE TABLE tmp7(ts TIMESTAMP);
INSERT INTO tmp7 values('1996-02-02 02:02:02'),(NOW());
SELECT * FROM tmp7;
ts |
-----------------------+
1996-02-02 02:02:02.000|
2022-09-11 15:53:41.421|
4、创建带时区的日期和时间类型
CREATE TABLE tmp7h(th TIME with time zone);
INSERT INTO tmp7h values('10:05:05 PST'),('10:05:05');
SELECT * FROM tmp7h;
th |
--------------+
02:05:05 +0800|
10:05:05 +0800|
4.1.5 字符串类型
字符串类型用来存储字符串数据,除了可以存储字符串数据之外,还可以存储其他数据,比如图片和声音的二进制
数据。字符串可以进行区分或者不区分大小写的串比较,另外,还可以进行模式匹配查找。PostgreSQL中字符串
类型指CHAR
、VARCHAR
和TEXT
。
类型名称 | 说明 |
---|---|
CHAR(n)/CHARACTER(n) |
固定长度非二进制字符串,不足补空白 |
VARCHAR(n)/CHARACTER VARYING(n) |
变长非二进制字符串,有长度限制 |
TEXT |
变长非二进制字符串,无长度限制 |
1、CHARACTER(n)和 CHARACTER VARYING(n)
其中,n是一个正整数。CHARACTER(n)
和CHARACTER VARYING(n)
都可以存储最多n个字符的字符串。试图存储
更长的字符串到这些类型的字段里会产生一个错误,除非超出长度的字符都是空白,这种情况下该字符串将被截断
为最大长度。如果要存储的字符串比声明的长度短,类型为CHARACTER的数值将会用空白填满;而类型为
CHARACTER VARYING的数值将只是存储较短的字符串。
CREATE TABLE tmp8(
ch CHARACTER(4),vch CHARACTER VARYING(4)
);
INSERT INTO tmp8 VALUES('ab','ab'),('abcd','abcd'),('ab','ab');
SELECT concat('(',ch,')'),concat('(',vch,')') FROM tmp8;
concat|concat|
------+------+
(ab )|(ab) |
(abcd)|(abcd)|
(ab )|(ab) |
CHARACTER类型中填充的空白是无意义的。例如在比较两个CHARACTER值时,填充的空白都会被忽略,在转换
成其他字符串类型的时候,CHARACTER 值里面的空白会被删除。请注意,在CHARACTER VARYING和TEXT数值
里,结尾的空白是有意义的。
# 会报错,长度超出限制
INSERT INTO tmp8 VALUES('abcde','abcde');
2、TEXT 类型
在PostgreSQL中,TEXT 类型可以存储任何长度的字符串。尽管TEXT 不是SQL 标准类型,但是其他许多SQL 数据
库系统中也包括它。
CREATE TABLE tmp9(te TEXT);
INSERT INTO tmp9 VALUES('ab'),('abcd'),('ab');
SELECT concat('(',te,')') FROM tmp9;
concat|
------+
(ab) |
(abcd)|
(ab) |
4.1.6 二进制类型
PostgreSQL 支持两类字符型数据:文本字符串和二进制字符串,前面讲解了存储文本的字符串类型,这一节将讲
解 PostgreSQL 中存储二进制数据的数据类型。PostgreSQL 提供了 BYTEA 类型,用于存储二进制字符串。BYTEA
类型存储空间为4字节加上实际的二进制字符串。
CREATE TABLE tmp10(b BYTEA);
INSERT INTO tmp10 VALUES(E'\\000');
SELECT * FROM tmp10;
b|
-+
|
4.1.7 布尔类型
PostgreSQL 提供了 BOOLEAN 布尔数据类型。BOOLEAN用一个字节来存储,提供了 TRUE(真)和FALSE(假)两个
值。另外,用户可以使用其他有效文本值替代TRUE和FALSE。替代 TRUE的文本值为:‘t’、‘true’、‘y’、‘yes’和1’;
替代FALSE的文本值为:'f、‘false’、‘n’、‘no’和’0’。
CREATE TABLE tmp11(b BOOLEAN);
INSERT INTO tmp11 VALUES(TRUE),
(FALSE),
('y'),
('no'),
('0');
SELECT * FROM tmp11;
b |
-----+
true |
false|
true |
false|
false|
4.1.8 数组类型
PostgreSQL 允许将字段定义成定长或变长的一维或多维数组。数组类型可以是任何基本类型或用户定义类型。
1、声明数组
在PostgreSQL中,一个数组类型是通过在数组元素类型名后面附加中括号来命名的。
numb INT[];
xuehao TEXT[][];
zuoye TEXT[4][4];
其中,numb字段为一维INT数组;xuehao字段为二维TEXT数组;zuoye字段为二维TEXT数组,并且声明了数组
的长度。不过,目前 PostgreSQL 并不强制数组的长度,所以声明长度和不声明长度是一样的。
另外对于一维数组,也可以使用SQL 标准声明,SQL 语句如下:
PAY_BY_QUARTER INT ARRAY[5];
此种声明方式,仍然不强制数组的长度。
2、插入数组数值
插入数组元素时,用大括号把数组元素括起来并且用逗号将它们分开。
CREATE TABLE tmp12(bt int[]);
INSERT INTO tmp12 VALUES('{
{1,1,1},{2,2,2},{3,3,3}}');
SELECT * FROM tmp12;
bt |
-------------------------+
{
{1,1,1},{2,2,2},{3,3,3}}|
4.2 如何选择数据类型
PostgreSQL 提供了大量的数据类型,为了优化存储,提高数据库性能,在任何情况下均应使用最精确的类型。即
在所有可以表示该列值的类型中,该类型使用的存储空间最少。
4.2.1 整数和浮点数
如果不需要小数部分,则使用整数来保存数据;如果需要表示小数,则使用浮点数类型。对于浮点数据列,存入的
数值会被该列定义的小数位进行四舍五入。例如,如果列的值的范围为1~99999,若使用整数,则INT是最好的类
型;若需要存储小数,则使用浮点数类型。
4.2.2 日期与时间类型
PostgreSQL 对于不同种类的日期和时间有很多的数据类型,比如 TIME 和DATE。如果只记录时间,则使用 TIME
类型即可;如果只记录日期,只需使用DATE 类型。如果同时需要记录日期和时间,则可以使用 TIMESTAMP 类
型。默认情况下,当插入一条记录但并没有指定 TIMESTAMP 这个列值时,PostgreSQL 会把TIMESTAMP 列设为
当前的时间,因此当需要插入记录时、同时插入当前时间,使用 TIMESTAMP是方便的。
4.2.3 CHAR与VARCHAR 之间的特点与选择
CHAR 和VARCHAR的区别:CHAR
是固定长度字符,VARCHAR
是可变长度字符。对于插入数据长度不够时,CHAR
会自动填充插入数据的尾部空格,VARCHAR则不会。
由于CHAR是固定长度,所以它的处理速度比 VARCHAR 要快,但缺点就是浪费存储空间。所以对于存储量不大,
但在速度上有要求的数据可以使用CHAR 类型,反之可以使用 VARCHAR类型来实现。
4.3 常见运算符
运算符是用来告诉 PostgreSQL 执行特定算术或逻辑操作的符号。PostgreSQL的内部运算符很丰富,主要有四大
类,具体如下。
4.3.1 算术运算符
用于各类数值运算。包括加(+
)、减(-
)、乘(*
)、除(/
)、求余(或称模运算,%
)。
CREATE TABLE tmp14(num INT);
INSERT INTO tmp14 VALUES(64);
SELECT num, num+10, num-10,num+5-3,num+36.5 FROM tmp14;
num|?column?|?column?|?column?|?column?|
---+--------+--------+--------+--------+
64| 74| 54| 66| 100.5|
SELECT num,num *2,num/2,num/3,num%3 FROM tmp14;
num|?column?|?column?|?column?|?column?|
---+--------+--------+--------+--------+
64| 128| 32| 21| 1|
# 报错
SELECT num, num /0, num %0 FROM tmp14;
4.3.2 比较运算符
用于比较运算。包括大于(>
)、小于(<
)、等于(=
)、大于等于(>=
)、小于等于(<=
)、不等于(<>
或者!=
)、以及
IN
、BETWEEN AND
、GREATEST
、LEAST
、LIKE
等。
1、等于运算符=
SELECT 1=0,'2'=2,2=2,'b'='b',(1+3)=(2+1),NULL=NULL;
?column?|?column?|?column?|?column?|?column?|?column?|
--------+--------+--------+--------+--------+--------+
false |true |true |true |false | |
等于运算符在进行数值比较时有如下规则:
-
若有一个或两个参数为 NULL,则比较运算的结果为空。
-
若同一个比较运算中的两个参数都是字符串,则按照字符串进行比较。
-
若两个参数均为整数,则按照整数进行比较。
-
若一个字符串和数字进行相等判断,则 PostgreSQL可以自动将字符串转换为数字。
2、不等于运算符<>或者!=
SELECT 'good'<>'god',1<>2,4!=4,5.5!=5,(1+3)!=(2+1),NULL<>NULL;
?column?|?column?|?column?|?column?|?column?|?column?|
--------+--------+--------+--------+--------+--------+
true |true |false |true |true | |
3、小于等于运算符<=
SELECT 'good'<='god',1<=2,4<=4,5.5<=5,(1+3)<=(2+1),NULL<=NULL;
?column?|?column?|?column?|?column?|?column?|?column?|
--------+--------+--------+--------+--------+--------+
false |true |true |false |false | |
4、小于运算符<
SELECT 'good'<'god',1<2,4<4,5.5<5,(1+3)<(2+1),NULL<NULL;
?column?|?column?|?column?|?column?|?column?|?column?|
--------+--------+--------+--------+--------+--------+
false |true |false |false |false | |
5、大于等于运算符>=
SELECT 'good'>='god',1>=2,4>=4,5.5>=5,(1+3)>=(2+1),NULL>=NULL;
?column?|?column?|?column?|?column?|?column?|?column?|
--------+--------+--------+--------+--------+--------+
true |false |true |true |true | |
6、大于运算符>
SELECT 'good'>'god',1>2,4>4,5.5>5,(1+3)>(2+1),NULL>NULL;
?column?|?column?|?column?|?column?|?column?|?column?|
--------+--------+--------+--------+--------+--------+
true |false |false |true |true | |
7、BETWEEN AND运算符
BETWEEN AND
:判断一个值是否落在两个值之间。
SELECT 4 BETWEEN 2 AND 5,4 BETWEEN 4 AND 6,12 BETWEEN 9 AND 10;
?column?|?column?|?column?|
--------+--------+--------+
true |true |false |
SELECT 'x' BETWEEN 'f' AND 'g','b' BETWEEN 'a' AND 'c';
?column?|?column?|
--------+--------+
false |true |
8、Last运算符
LEAST
:在有两个或多个参数时,返回最小值。
SELECT least(2,0),least(20.0,3.0,100.5),least('a','c','b'),least(10,NULL);
least|least|least|least|
-----+-----+-----+-----+
0| 3.0|a | 10|
9、GREATEST运算符
GREATEST
:当有两个或多个参数时,返回最大值。
SELECT greatest(2,0),greatest(20.0,3.0,100.5),greatest('a','c','b'),
greatest(10,NULL);
greatest|greatest|greatest|greatest|
--------+--------+--------+--------+
2| 100.5|c | 10|
10、IN、NOT IN运算符
IN
:判断一个值是否是IN列表中的任意一个值。
SELECT 2 IN(1,2,5,8),