MySQL表的增删查改

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] 表名 #截断表

区别:

  1. delete可以选择对表的部分或全部作删除,而truncate只能对整表操作
  2. truncate实际上MySQL不对数据操作,所以比delete更快,但是TRUNCATE在删除数据的时候,并不经过真正的事务,所以无法回滚。
  3. truncate会重置auto_increment项,delete不会

5. 聚合函数

将同一列中的值,作某些具体操作,统计得到一个结果,称为"聚合"。如,学生成绩表中,求出数学成绩的总和,就是对math列的全部值累加,得到最终结果。

函数 说明
count(* | expr) 返回查询到的数据的数量
sum(expr) 返回查询到的数据的总和
avg(expr) 返回查询到的数据的平均值
max(expr) 返回查询到的数据的最大值
min(expr) 返回查询到的数据的最小值
  1. 聚合函数可以加上distinct语句,即去重后再统计,如count(distinct [col1],[col2], ...)

    sql 复制代码
    mysql> 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)
  2. 对于数学运算的聚合函数,无法计算的返回0(例如:字符串类型可以求最大值最小值,但是无法求总和或平均值)

    sql 复制代码
    mysql> 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)
  3. 默认情况下,聚合函数忽略列值为NULL的行,不参与计算。ifnull函数,用于想要使列值为NULL的行也参与聚合统计,如:计算一组学生的最低数学成绩,若数学成绩math为NULL,则视为零分参与计算,select min(ifnull(math,0)) from students

    sql 复制代码
    mysql> 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相同的成一组)

    sql 复制代码
    mysql> 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用的的列)是一定相同的,可以作为一个独立的值在一行显示出来,而其它列不一定相同,无法在同一行显示出来。

  • 显示每个部门的每种岗位的平均工资和最高工资(分组再分组,每一组的标识是部门+岗位)

    sql 复制代码
    mysql> 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的作用是分组条件过滤havinggroup 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的作用类似,但有些区别:

  1. where 在数据被分组前进行筛选,作用于行级别的数据。
  2. having 在数据被分组后进行筛选,作用于分组级别的数据。
相关推荐
web2u1 小时前
MySQL 中如何进行 SQL 调优?
java·数据库·后端·sql·mysql·缓存
新知图书3 小时前
MySQL用户授权、收回权限与查看权限
数据库·mysql·安全
文城5213 小时前
Mysql存储过程(学习自用)
数据库·学习·mysql
沉默的煎蛋3 小时前
MyBatis 注解开发详解
java·数据库·mysql·算法·mybatis
C语言扫地僧3 小时前
MySQL 事务及MVCC机制详解
数据库·mysql
小镇cxy3 小时前
MySQL事物,MVCC机制
数据库·mysql
雾里看山4 小时前
【MySQL】 库的操作
android·数据库·笔记·mysql
꧁瀟洒辵1恛꧂5 小时前
从新手到高手的蜕变:MySQL 视图进阶全攻略
数据库·mysql
doubt。17 小时前
【BUUCTF】[RCTF2015]EasySQL1
网络·数据库·笔记·mysql·安全·web安全
小辛学西嘎嘎17 小时前
MVCC在MySQL中实现无锁的原理
数据库·mysql