1. 插入数据insert
CRUD中的"C",Create,即向表中插入新的数据,常用sql命令:
insert
insert
可以选定列插入,并x`支持同时插入多行数据(中括号内为可选项)
sql
insert [into] 表名 [(column1, column2, column3...)] values (value1), (value2), (value3)...
value必须与指定的列匹配,不指定列,默认就是全列插入。
sql
mysql> insert into students (sn, name, qq) value (103, '子乔', 451592222), (104, '小贤', 451593333), (105, '一菲', 123456789);
Query OK, 3 rows affected (0.01 sec)
Records: 3 Duplicates: 0 Warnings: 0
mysql> select * from students;
+----+-----+--------+-----------+
| id | sn | name | qq |
+----+-----+--------+-----------+
| 1 | 101 | 张伟 | 451591111 |
| 2 | 102 | 张伟 | 451591111 |
| 3 | 103 | 子乔 | 451592222 |
| 4 | 104 | 小贤 | 451593333 |
| 5 | 105 | 一菲 | 123456789 |
+----+-----+--------+-----------+
insert
插入数据时,若发生主键或唯一键冲突,一般情况下MySQL会报错 。在insert
语句后接上on duplicate key update col1=val1, col2=val2...
,当发生主键或者唯一键冲突时,冲突元组列col1, col2...的值修改为用户指定的值val1, val2...。
sql
mysql> select * from students;
+----+-----+--------+-----------+
| id | sn | name | qq |
+----+-----+--------+-----------+
| 1 | 101 | 张伟 | 451591111 |
| 2 | 106 | 关谷 | 451594567 |
| 4 | 104 | 小贤 | 451593333 |
| 5 | 105 | 一菲 | 123456789 |
| 9 | 107 | 婉瑜 | 123123123 |
+----+-----+--------+-----------+
5 rows in set (0.00 sec)
mysql> insert into students value (2, 103, '子乔', 451522222);
ERROR 1062 (23000): Duplicate entry '2' for key 'PRIMARY' #这里发生了主键冲突,无法插入,报错
mysql> insert into students value (2, 103, '子乔', 451522222) on duplicate key update sn='103', name='子乔', qq='451522222';#这次虽然依然主键冲突,但是修改了冲突那一行的一些值
Query OK, 2 rows affected (0.00 sec)
mysql> select * from students;
+----+-----+--------+-----------+
| id | sn | name | qq |
+----+-----+--------+-----------+
| 1 | 101 | 张伟 | 451591111 |
| 2 | 103 | 子乔 | 451522222 |
| 4 | 104 | 小贤 | 451593333 |
| 5 | 105 | 一菲 | 123456789 |
| 9 | 107 | 婉瑜 | 123123123 |
+----+-----+--------+-----------+
5 rows in set (0.00 sec)
replace
,语法和insert
基本一样
sql
replace [into] 表名 [(column, column, column...)] values (value_list), (value_list), (value_list)...
-
主键或唯一键冲突,删除后插入
-
主键或唯一键不冲突,直接插入
2. 查询数据select
CRUD中的"R",Retrive,即向从表中查询数据,常用sql命令:
select
,select搭配一些限制命令使用,如:distinct, where, order, limit等
distinct
结果去重,对于重复的数据只显示一次。
sql
SELECT DISTINCT column1, column2, column3 FROM your_table;
注意:distinct保证的是紧随其后所有列组合在一起的唯一性
sql
mysql> select * from exam;
+----+--------+---------+------+---------+
| id | name | chinese | math | english |
+----+--------+---------+------+---------+
| 1 | 张三 | 19 | 36 | 24 |
| 2 | 李四 | 11 | 83 | 83 |
| 3 | 王五 | 67 | 83 | 14 |
| 4 | 赵六 | 22 | 68 | 74 |
| 5 | 小明 | 64 | 99 | 74 |
| 6 | 张飞 | 23 | 43 | 48 |
| 7 | 刘备 | 28 | 97 | 9 |
| 8 | 刘备 | 55 | 97 | 71 |
+----+--------+---------+------+---------+
8 rows in set (0.00 sec)
mysql> select distinct math from exam; #保证数学成绩math的唯一性
+------+
| math |
+------+
| 36 |
| 83 |
| 68 |
| 99 |
| 43 |
| 97 |
+------+
6 rows in set (0.00 sec)
mysql> select distinct name,math from exam; #保证姓名+数学成绩的唯一性
+--------+------+
| name | math |
+--------+------+
| 张三 | 36 |
| 李四 | 83 |
| 王五 | 83 |
| 赵六 | 68 |
| 小明 | 99 |
| 张飞 | 43 |
| 刘备 | 97 |
+--------+------+
7 rows in set (0.00 sec)
# 34行和35行,姓名不同,数学成绩相同,整体不同,可以共存
# "刘备 97"存在两行,因此被去重了
where
比较运算符
运算符 | 说明 |
---|---|
大于 | |
>= | 大于等于 |
< | 小于 |
<= | 小于等于 |
= | 等于,NULL 不安全,例如 NULL = NULL 的结果是 NULL |
<=> | 等于,NULL 安全,例如 NULL <=> NULL 的结果是 TRUE(1) |
!=, <> | 不等于 |
BETWEEN a AND b | 范围匹配,全闭区间[a, b],如果 a <= value <= ab,返回 TRUE(1) |
IN | 如果是 option 中的任意一个,返回 TRUE(1) |
IS NULL | 是 NULL |
IS NOT NULL | 不是 NULL |
LIKE | 模糊匹配。% 表示任意多个(包括 0 个)任意字符;_ 表示一个字符 |
一般情况下,NULL不安全,不参与比较,因此只要运算符左右任一侧带有NULL,返回结果为NULL。特殊情况是<=>
逻辑运算符
AND
,与OR
,或NOT
,非
order
默认是升序
asc
: 升序
desc
: 降序
limit
对显式行数的限制
limit n
: 从开始连续显示n行limit s,n
: 从第s行开始,连续显示n行(起始行下标为0)limit n offset s
:同上
使用limit对表进行分页显示
sql
mysql> select * from exam order by id limit 3 offset 0;
+----+--------+---------+------+---------+
| id | name | chinese | math | english |
+----+--------+---------+------+---------+
| 1 | 张三 | 35 | 36 | 24 |
| 2 | 李四 | 27 | 83 | 83 |
| 3 | 王五 | 83 | 83 | 14 |
+----+--------+---------+------+---------+
3 rows in set (0.00 sec)
mysql> select * from exam order by id limit 3 offset 3;
+----+--------+---------+------+---------+
| id | name | chinese | math | english |
+----+--------+---------+------+---------+
| 4 | 赵六 | 38 | 68 | 74 |
| 5 | 小明 | 80 | 99 | 82 |
| 6 | 张飞 | 39 | 43 | 48 |
+----+--------+---------+------+---------+
3 rows in set (0.00 sec)
mysql> select * from exam order by id limit 3 offset 6;
+----+--------+---------+------+---------+
| id | name | chinese | math | english |
+----+--------+---------+------+---------+
| 7 | 刘备 | 44 | 97 | 9 |
| 8 | 刘备 | 71 | 97 | 71 |
| 10 | 悟空 | 98 | NULL | NULL |
+----+--------+---------+------+---------+
3 rows in set (0.00 sec)
mysql> select * from exam order by id limit 3 offset 9;
+----+-----------+---------+------+---------+
| id | name | chinese | math | english |
+----+-----------+---------+------+---------+
| 11 | 张三丰 | 76 | 60 | 60 |
+----+-----------+---------+------+---------+
1 row in set (0.00 sec)
3. 更新数据update
CRUD中的"U",Update,即更新表中的某些数据,常用sql命令:
update
更新筛选出来的数据记录,不加筛选字段默认更新整表数据,要小心谨慎!
sql
update 表名 set col1=val, col2=val... /*筛选字段:*/ [where...][order by...][limit...]
Demo:将总成绩倒数前三的同学的英语成绩都加上10分
sql
mysql> select name,english,chinese+math+english as total from exam order by total limit 3;
+--------+---------+-------+
| name | english | total |
+--------+---------+-------+
| 张三 | 24 | 125 |
| 刘备 | 9 | 150 |
| 张飞 | 48 | 160 |
+--------+---------+-------+
3 rows in set (0.00 sec)
mysql> update exam set english=english+10 order by chinese+math+english asc limit 3;
Query OK, 3 rows affected (0.00 sec)
Rows matched: 3 Changed: 3 Warnings: 0
mysql> select name,english,chinese+math+english as total from exam order by total limit 3;
+--------+---------+-------+
| name | english | total |
+--------+---------+-------+
| 张三 | 34 | 135 |
| 刘备 | 19 | 160 |
| 张飞 | 58 | 170 |
+--------+---------+-------+
4. 删除数据delete
CRUD中的"D",Delete,即删除表中的某些数据,常用sql命令:
delete
删除筛选出来的数据记录,不加筛选字段默认删除整表数据,要小心谨慎!
sql
delete from 表名 /*筛选字段:*/ [where...][order by...][limit...]
清空表中所有内容:
sql
delete from 表名
truncate [table] 表名 #截断表
区别:
delete
可以选择对表的部分或全部作删除,而truncate
只能对整表操作truncate
实际上MySQL不对数据操作,所以比delete
更快,但是TRUNCATE在删除数据的时候,并不经过真正的事务,所以无法回滚。truncate
会重置auto_increment项,delete
不会
5. 聚合函数
将同一列中的值,作某些具体操作,统计得到一个结果,称为"聚合"。如,学生成绩表中,求出数学成绩的总和,就是对math列的全部值累加,得到最终结果。
函数 | 说明 |
---|---|
count(* | expr) | 返回查询到的数据的数量 |
sum(expr) | 返回查询到的数据的总和 |
avg(expr) | 返回查询到的数据的平均值 |
max(expr) | 返回查询到的数据的最大值 |
min(expr) | 返回查询到的数据的最小值 |
-
聚合函数可以加上
distinct
语句,即去重后再统计,如count(distinct [col1],[col2], ...)
sqlmysql> select ename, deptno from emp; +--------+--------+ | ename | deptno | +--------+--------+ | SMITH | 20 | | ALLEN | 30 | | WARD | 30 | | JONES | 20 | | MARTIN | 30 | | BLAKE | 30 | | CLARK | 10 | | SCOTT | 20 | | KING | 10 | | TURNER | 30 | | ADAMS | 20 | | JAMES | 30 | | FORD | 20 | | MILLER | 10 | +--------+--------+ 14 rows in set (0.00 sec) mysql> select count(deptno) from emp; +---------------+ | count(deptno) | +---------------+ | 14 | +---------------+ 1 row in set (0.00 sec) mysql> select count(distinct deptno) from emp; #一共有多少个不同的部门 +------------------------+ | count(distinct deptno) | +------------------------+ | 3 | +------------------------+ 1 row in set (0.00 sec)
-
对于数学运算的聚合函数,无法计算的返回0(例如:字符串类型可以求最大值最小值,但是无法求总和或平均值)
sqlmysql> select deptno, max(ename) from emp group by deptno; +--------+------------+ | deptno | max(ename) | +--------+------------+ | 10 | MILLER | | 20 | SMITH | | 30 | WARD | +--------+------------+ 3 rows in set (0.00 sec) mysql> select deptno, sum(ename) from emp group by deptno; +--------+------------+ | deptno | sum(ename) | +--------+------------+ | 10 | 0 | | 20 | 0 | | 30 | 0 | +--------+------------+ 3 rows in set, 14 warnings (0.00 sec) mysql> select deptno, avg(ename) from emp group by deptno; +--------+------------+ | deptno | avg(ename) | +--------+------------+ | 10 | 0 | | 20 | 0 | | 30 | 0 | +--------+------------+ 3 rows in set, 14 warnings (0.00 sec) mysql> select deptno, min(ename) from emp group by deptno; +--------+------------+ | deptno | min(ename) | +--------+------------+ | 10 | CLARK | | 20 | ADAMS | | 30 | ALLEN | +--------+------------+ 3 rows in set (0.00 sec)
-
默认情况下,聚合函数忽略列值为
NULL
的行,不参与计算。ifnull
函数,用于想要使列值为NULL
的行也参与聚合统计,如:计算一组学生的最低数学成绩,若数学成绩math为NULL
,则视为零分参与计算,select min(ifnull(math,0)) from students
。sqlmysql> select * from students; +----+-----+--------+-----------+------+ | id | sn | name | qq | math | +----+-----+--------+-----------+------+ | 1 | 101 | 张伟 | 451591111 | 50 | | 2 | 103 | 子乔 | 451522222 | 50 | | 4 | 104 | 小贤 | 451593333 | 50 | | 5 | 105 | 一菲 | 123456789 | 50 | | 9 | 107 | 婉瑜 | 123123123 | NULL | +----+-----+--------+-----------+------+ 5 rows in set (0.00 sec) mysql> select min(math) from students; +-----------+ | min(math) | +-----------+ | 50 | +-----------+ 1 row in set (0.00 sec) mysql> select min(ifnull(math,0)) from students; +---------------------+ | min(ifnull(math,0)) | +---------------------+ | 0 | +---------------------+ 1 row in set (0.00 sec)
6. 分组聚合查询group by
将一个"大表"拆分成多个"小表",这就是分组。对于每一个"小表",都有自己的聚合结果,这就是分组聚合。
聚合函数又称组函数,实际上就是对一个组中的某些数据作聚合操作,得出一个具体结果。上面介绍是一种特殊情况,即将整个表看作一个组,下面是将表分为多个组,对每个组进行聚合。
group by col
:根据col
列进行分组。
-
显示每个部门的最低工资和平均工资(按deptno分组,
group by deptno
,deptno相同的成一组)sqlmysql> select deptno, min(sal), avg(sal) from emp group by deptno; +--------+----------+-------------+ | deptno | min(sal) | avg(sal) | +--------+----------+-------------+ | 10 | 1300.00 | 2916.666667 | | 20 | 800.00 | 2175.000000 | | 30 | 950.00 | 1566.666667 | +--------+----------+-------------+ 3 rows in set (0.00 sec)
用于分组的列dept
可以不显示,但是为了便于观察不同分组的聚合情况,最好还是加上。
分组聚合后的表,其中的一行,是某个组("小表")聚合组内多个数据并且经过某种运算得出的结果,每一组只有用于分组(可理解为标识该组唯一性)的列(即
group by
用的的列)是一定相同的,可以作为一个独立的值在一行显示出来,而其它列不一定相同,无法在同一行显示出来。
-
显示每个部门的每种岗位的平均工资和最高工资(分组再分组,每一组的标识是部门+岗位)
sqlmysql> select deptno, job, avg(sal) as 平均工资, max(sal) as 最高工资 from emp group by deptno, job; +--------+-----------+--------------+--------------+ | deptno | job | 平均工资 | 最高工资 | +--------+-----------+--------------+--------------+ | 10 | CLERK | 1300.000000 | 1300.00 | | 10 | MANAGER | 2450.000000 | 2450.00 | | 10 | PRESIDENT | 5000.000000 | 5000.00 | | 20 | ANALYST | 3000.000000 | 3000.00 | | 20 | CLERK | 950.000000 | 1100.00 | | 20 | MANAGER | 2975.000000 | 2975.00 | | 30 | CLERK | 950.000000 | 950.00 | | 30 | MANAGER | 2850.000000 | 2850.00 | | 30 | SALESMAN | 1400.000000 | 1600.00 | +--------+-----------+--------------+--------------+ 9 rows in set (0.00 sec)
having
having
的作用是分组条件过滤 。having
和group by
配合使用,对分组聚合的结果进行条件过滤
- 显示平均工资低于2000的部门和它的平均工资
sql
mysql> select deptno, avg(sal) as 平均工资 from emp group by deptno having 平均工资 < 2000;
+--------+--------------+
| deptno | 平均工资 |
+--------+--------------+
| 30 | 1566.666667 |
+--------+--------------+
1 row in set (0.00 sec)
having和where的作用类似,但有些区别:
where
在数据被分组前进行筛选,作用于行级别的数据。having
在数据被分组后进行筛选,作用于分组级别的数据。