首先创建一张学生表:
mysql> create table students(
-> id int unsigned primary key auto_increment,
-> sn int not null unique,
-> name varchar(20) not null,
-> qq varchar(20) unique
-> );
insert into students values (10, 111, '公孙离', 12345);
insert students (sn, name, qq) values (222, '孙策', 23456);
insert students values (20, 333, '貂蝉', 34567), (30, 444, '吕布', 45678);
mysql> select * from students;
+----+-----+-----------+-------+
| id | sn | name | qq |
+----+-----+-----------+-------+
| 10 | 111 | 公孙离 | 12345 |
| 11 | 222 | 孙策 | 23456 |
| 20 | 333 | 貂蝉 | 34567 |
| 30 | 444 | 吕布 | 45678 |
+----+-----+-----------+-------+
4 rows in set (0.00 sec)
由于主键或者唯一键对应的值已经存在而导致插入失败。
--主键冲突
mysql> insert students values (30, 555, '狄仁杰', 56789);
ERROR 1062 (23000): Duplicate entry '30' for key 'students.PRIMARY'
--唯一键冲突
mysql> insert students values (31, 444, '狄仁杰', 56789);
ERROR 1062 (23000): Duplicate entry '444' for key 'students.sn'
可以选择性的进行同步更新操作语法:
insert ... on duplicate key update
column = value [, column = value] ...
mysql> insert students values (31, 444, '狄仁杰', 56789)
-> on duplicate key update id = 30, sn = 555, name = '狄仁杰', qq = 56789;
Query OK, 2 rows affected (0.00 sec)
mysql> insert students values (31, 444, '狄仁杰', 56789)
-> on duplicate key update id = 31, sn = 444, name = '狄仁杰', qq = 56789;
Query OK, 2 rows affected (0.02 sec)
操作成功后的提示信息:
mysql> select * from students;
+----+-----+-----------+-------+
| id | sn | name | qq |
+----+-----+-----------+-------+
| 10 | 111 | 公孙离 | 12345 |
| 11 | 222 | 孙策 | 23456 |
| 20 | 333 | 貂蝉 | 34567 |
| 31 | 444 | 狄仁杰 | 56789 |
+----+-----+-----------+-------+
4 rows in set (0.00 sec)
mysql> replace students (id, sn, name) values (32, 555, '百里守约');
Query OK, 1 row affected (0.01 sec)
mysql> replace into students values (11, 666, '后羿', 67890);
Query OK, 2 rows affected (0.02 sec)
mysql> select * from students;
+----+-----+--------------+-------+
| id | sn | name | qq |
+----+-----+--------------+-------+
| 10 | 111 | 公孙离 | 12345 |
| 11 | 666 | 后羿 | 67890 |
| 20 | 333 | 貂蝉 | 34567 |
| 31 | 444 | 狄仁杰 | 56789 |
| 32 | 555 | 百里守约 | NULL |
+----+-----+--------------+-------+
5 rows in set (0.00 sec)
创建测试表:
mysql> create table exam_result (
-> id int unsigned primary key auto_increment,
-> name varchar(20) not NULL comment '同学姓名',
-> chinese float default 0.0 comment '语文成绩',
-> math float default 0.0 comment '数学成绩',
-> english float default 0.0 comment '英语成绩'
-> );
mysql> desc exam_result;
+---------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------+--------------+------+-----+---------+----------------+
| id | int unsigned | NO | PRI | NULL | auto_increment |
| name | varchar(20) | NO | | NULL | |
| chinese | float | YES | | 0 | |
| math | float | YES | | 0 | |
| english | float | YES | | 0 | |
+---------+--------------+------+-----+---------+----------------+
5 rows in set (0.00 sec)
插入测试数据:
mysql> insert exam_result (name, chinese, math, english) values
-> ('唐三藏', 67, 98, 56),
-> ('孙悟空', 87, 78, 77),
-> ('猪悟能', 88, 98, 90),
-> ('曹孟德', 82, 84, 67),
-> ('刘玄德', 55, 85, 45),
-> ('孙权', 70, 73, 78),
-> ('宋公明', 75, 65, 30);
mysql> select * from exam_result;
+----+-----------+---------+------+---------+
| id | name | chinese | math | english |
+----+-----------+---------+------+---------+
| 1 | 唐三藏 | 67 | 98 | 56 |
| 2 | 孙悟空 | 87 | 78 | 77 |
| 3 | 猪悟能 | 88 | 98 | 90 |
| 4 | 曹孟德 | 82 | 84 | 67 |
| 5 | 刘玄德 | 55 | 85 | 45 |
| 6 | 孙权 | 70 | 73 | 78 |
| 7 | 宋公明 | 75 | 65 | 30 |
+----+-----------+---------+------+---------+
7 rows in set (0.00 sec)
mysql> select name, math from exam_result;
+-----------+------+
| name | math |
+-----------+------+
| 唐三藏 | 98 |
| 孙悟空 | 78 |
| 猪悟能 | 98 |
| 曹孟德 | 84 |
| 刘玄德 | 85 |
| 孙权 | 73 |
| 宋公明 | 65 |
+-----------+------+
7 rows in set (0.00 sec)
mysql> select id, name, english + 10 from exam_result;
+----+-----------+--------------+
| id | name | english + 10 |
+----+-----------+--------------+
| 1 | 唐三藏 | 66 |
| 2 | 孙悟空 | 87 |
| 3 | 猪悟能 | 100 |
| 4 | 曹孟德 | 77 |
| 5 | 刘玄德 | 55 |
| 6 | 孙权 | 88 |
| 7 | 宋公明 | 40 |
+----+-----------+--------------+
7 rows in set (0.07 sec)
mysql> select id, name, chinese + math + english as 总分 from exam_result;
+----+-----------+--------+
| id | name | 总分 |
+----+-----------+--------+
| 1 | 唐三藏 | 221 |
| 2 | 孙悟空 | 242 |
| 3 | 猪悟能 | 276 |
| 4 | 曹孟德 | 233 |
| 5 | 刘玄德 | 185 |
| 6 | 孙权 | 221 |
| 7 | 宋公明 | 170 |
+----+-----------+--------+
7 rows in set (0.01 sec)
mysql> select distinct chinese from exam_result;
+---------+
| chinese |
+---------+
| 67 |
| 87 |
| 88 |
| 82 |
| 70 |
| 75 |
+---------+
6 rows in set (0.00 sec)
比较运算符 | 说明 |
---|---|
>, >=, <, <= | 大于,大于等于,小于,小于等于 |
= | 等于,null 不安全,例如 null = null 的结果是 null |
<=> | 等于,null 安全,例如 null <=> null 的结果是 true(1) |
!=, <> | 不等于 |
between a0 and a1 | 范围匹配,[a0, a1],如果 a0 <= value <= a1,返回 true(1) |
in (option, …) | 如果是 option 中的任意一个,返回 true(1) |
is null | 是 null |
is not null | 不是 null |
like | 模糊匹配。% 表示任意多个(包括 0 个)任意字符;_ 表示任意一个字符 |
逻辑运算符 | 说明 |
---|---|
AND | 多个条件必须都为 true(1),结果才是 true(1) |
OR | 任意一个条件为 true(1), 结果为 true(1) |
NOT | 条件为 true(1),结果为 false(0) |
mysql> select name, english from exam_result where english < 60;
+-----------+---------+
| name | english |
+-----------+---------+
| 唐三藏 | 56 |
| 刘玄德 | 45 |
| 宋公明 | 30 |
+-----------+---------+
3 rows in set (0.00 sec)
mysql> select name, chinese from exam_result
-> where chinese between 80 and 90;
+-----------+---------+
| name | chinese |
+-----------+---------+
| 孙悟空 | 87 |
| 猪悟能 | 88 |
| 曹孟德 | 82 |
| 刘玄德 | 88 |
+-----------+---------+
4 rows in set (0.00 sec)
mysql> select name, math from exam_result where math in (58, 59, 98, 99);
+-----------+------+
| name | math |
+-----------+------+
| 唐三藏 | 98 |
| 猪悟能 | 98 |
+-----------+------+
2 rows in set (0.00 sec)
mysql> select name from exam_result where name like '孙%';
+-----------+
| name |
+-----------+
| 孙悟空 |
| 孙权 |
+-----------+
2 rows in set (0.00 sec)
mysql> select name from exam_result where name like '孙_';
+--------+
| name |
+--------+
| 孙权 |
+--------+
1 row in set (0.00 sec)
mysql> select name, chinese, english from exam_result
-> where chinese > english;
+-----------+---------+---------+
| name | chinese | english |
+-----------+---------+---------+
| 唐三藏 | 67 | 56 |
| 孙悟空 | 87 | 77 |
| 曹孟德 | 82 | 67 |
| 刘玄德 | 88 | 45 |
| 宋公明 | 75 | 30 |
+-----------+---------+---------+
5 rows in set (0.00 sec)
mysql> select name, chinese + math + english 总分 from exam_result
-> where chinese + math + english < 200;
+-----------+--------+
| name | 总分 |
+-----------+--------+
| 宋公明 | 170 |
+-----------+--------+
1 row in set (0.00 sec)
mysql> select name, chinese + math + english 总分 from exam_result
-> where 总分 < 200;
ERROR 1054 (42S22): Unknown column '总分' in 'where clause'
这里明明给 chinese + math + english 取了别名,怎么在where条件中不能用呢? 这和 select 语句的执行顺序有关:
首先判断查询哪个表 —> 然后判断条件是什么 —> 最后判断查什么
mysql> select name, chinese from exam_result where
-> chinese > 80 and name not like '孙%';
+-----------+---------+
| name | chinese |
+-----------+---------+
| 猪悟能 | 88 |
| 曹孟德 | 82 |
| 刘玄德 | 88 |
+-----------+---------+
3 rows in set (0.00 sec)
mysql> select name, chinese, math, english, chinese + math + english 总分
-> from exam_result where name like '孙_' or chinese + math + english > 200
-> and chinese < math and english > 80;
+-----------+---------+------+---------+--------+
| name | chinese | math | english | 总分 |
+-----------+---------+------+---------+--------+
| 猪悟能 | 88 | 98 | 90 | 276 |
| 孙权 | 70 | 73 | 78 | 221 |
+-----------+---------+------+---------+--------+
2 rows in set (0.00 sec)
select ... from table_name [where ...] order by ...
没有 order by 子句的查询,返回的顺序是未定义的。
mysql> select name, math from exam_result order by math;
+-----------+------+
| name | math |
+-----------+------+
| 宋公明 | 65 |
| 孙权 | 73 |
| 孙悟空 | 78 |
| 曹孟德 | 84 |
| 刘玄德 | 85 |
| 唐三藏 | 98 |
| 猪悟能 | 98 |
+-----------+------+
7 rows in set (0.00 sec)
mysql> select name, chinese + english + math 总分
->from exam_result order by 总分 desc;
+-----------+--------+
| name | 总分 |
+-----------+--------+
| 猪悟能 | 276 |
| 孙悟空 | 242 |
| 曹孟德 | 233 |
| 唐三藏 | 221 |
| 孙权 | 221 |
| 刘玄德 | 218 |
| 宋公明 | 170 |
+-----------+--------+
7 rows in set (0.00 sec)
和where条件不同的是,order by 后面可以用别名,这还是和select语句的执行顺序有关,这里是先要有合适的数据,然后才能排序。
mysql> select name, math from exam_result where name like '孙%'
-> or name like '曹%' order by math desc;
+-----------+------+
| name | math |
+-----------+------+
| 曹孟德 | 84 |
| 孙悟空 | 78 |
| 孙权 | 73 |
+-----------+------+
3 rows in set (0.00 sec)
select ... from table_name [where ...] [order by ...] limit n;
select ... from table_name [where ...] [order by ...] limit s, n;
select ... from table_name [where ...] [order by ...] limit n offset s;
对未知表进行查询时,最好加一条 limit 1,避免因为表中数据过大,查询全表数据导致数据库卡死。
-- 第一页
mysql> select id, name, chinese, math, english from exam_result
-> order by id limit 3 offset 0;
+----+-----------+---------+------+---------+
| id | name | chinese | math | english |
+----+-----------+---------+------+---------+
| 1 | 唐三藏 | 67 | 98 | 56 |
| 2 | 孙悟空 | 87 | 78 | 77 |
| 3 | 猪悟能 | 88 | 98 | 90 |
+----+-----------+---------+------+---------+
3 rows in set (0.00 sec)
-- 第二页
mysql> select id, name, chinese, math, english from exam_result
-> order by id limit 3 offset 3;
+----+-----------+---------+------+---------+
| id | name | chinese | math | english |
+----+-----------+---------+------+---------+
| 4 | 曹孟德 | 82 | 84 | 67 |
| 5 | 刘玄德 | 88 | 85 | 45 |
| 6 | 孙权 | 70 | 73 | 78 |
+----+-----------+---------+------+---------+
3 rows in set (0.00 sec)
-- 第三页
mysql> select id, name, chinese, math, english from exam_result
-> order by id limit 3 offset 6;
+----+-----------+---------+------+---------+
| id | name | chinese | math | english |
+----+-----------+---------+------+---------+
| 7 | 宋公明 | 75 | 65 | 30 |
+----+-----------+---------+------+---------+
1 row in set (0.00 sec)
如果数据量不足不会有影响。
对查询到的结果进行列值更新。
mysql> update exam_result set math = 80 where name = '孙悟空';
Query OK, 1 row affected (0.03 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> select name, math from exam_result where name = '孙悟空';
+-----------+------+
| name | math |
+-----------+------+
| 孙悟空 | 80 |
+-----------+------+
1 row in set (0.00 sec)
mysql> update exam_result set math = 60, chinese = 70 where name = '曹孟德';
Query OK, 1 row affected (0.02 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> select name, math, chinese from exam_result where name = '曹孟德';
+-----------+------+---------+
| name | math | chinese |
+-----------+------+---------+
| 曹孟德 | 60 | 70 |
+-----------+------+---------+
1 row in set (0.00 sec)
MySQL不支持
+=
操作。
mysql> update exam_result set math = math + 30
-> order by chinese + math + english limit 3;
Query OK, 3 rows affected (0.01 sec)
Rows matched: 3 Changed: 3 Warnings: 0
mysql> select name, math, chinese + math + english 总分 from exam_result
-> order by 总分;
+-----------+------+--------+
| name | math | 总分 |
+-----------+------+--------+
| 曹孟德 | 90 | 227 |
| 宋公明 | 125 | 230 |
| 孙悟空 | 80 | 244 |
| 刘玄德 | 115 | 248 |
| 唐三藏 | 128 | 251 |
| 孙权 | 103 | 251 |
| 猪悟能 | 98 | 276 |
+-----------+------+--------+
7 rows in set (0.00 sec)
mysql> update exam_result set chinese = chinese * 2;
Query OK, 7 rows affected (0.04 sec)
Rows matched: 7 Changed: 7 Warnings: 0
mysql> select name, chinese from exam_result;
+-----------+---------+
| name | chinese |
+-----------+---------+
| 唐三藏 | 134 |
| 孙悟空 | 174 |
| 猪悟能 | 176 |
| 曹孟德 | 140 |
| 刘玄德 | 176 |
| 孙权 | 140 |
| 宋公明 | 150 |
+-----------+---------+
7 rows in set (0.00 sec)
delete from table_name [where ...] [order by ...] [limit ...];
mysql> delete from exam_result where name = '孙悟空';
Query OK, 1 row affected (0.00 sec)
mysql> select * from exam_result where name = '孙悟空';
Empty set (0.00 sec)
mysql> select * from for_delete;
+----+------+
| id | name |
+----+------+
| 1 | A |
| 2 | B |
| 3 | C |
+----+------+
3 rows in set (0.00 sec)
mysql> delete from for_delete;
Query OK, 3 rows affected (0.04 sec)
mysql> insert for_delete (name) values ('D');
Query OK, 1 row affected (0.02 sec)
mysql> select * from for_delete;
+----+------+
| id | name |
+----+------+
| 4 | D |
+----+------+
1 row in set (0.00 sec)
truncate [table] table_name;
mysql> select * from for_truncate;
+----+------+
| id | name |
+----+------+
| 1 | A |
| 2 | B |
| 3 | C |
+----+------+
3 rows in set (0.00 sec)
mysql> truncate for_truncate;
Query OK, 0 rows affected (0.22 sec)
mysql> insert for_truncate (name) values ('D');
Query OK, 1 row affected (0.03 sec)
mysql> select * from for_truncate;
+----+------+
| id | name |
+----+------+
| 1 | D |
+----+------+
1 row in set (0.02 sec)
现在有个要求,删除表中的重复数据。
比如下面的测试表:
mysql> select * from duplicate_table;
+------+------+
| id | name |
+------+------+
| 100 | aaa |
| 100 | aaa |
| 200 | bbb |
| 200 | bbb |
| 200 | bbb |
| 300 | ccc |
+------+------+
6 rows in set (0.00 sec)
思路:
mysql> create table no_duplicate_table like duplicate_table;
Query OK, 0 rows affected (0.11 sec)
mysql> insert no_duplicate_table select distinct * from duplicate_table;
Query OK, 3 rows affected (0.03 sec)
Records: 3 Duplicates: 0 Warnings: 0
mysql> rename table duplicate_table to old_duplicate_table,
-> no_duplicate_table to duplicate_table;
Query OK, 0 rows affected (0.15 sec)
mysql> select * from duplicate_table;
+------+------+
| id | name |
+------+------+
| 100 | aaa |
| 200 | bbb |
| 300 | ccc |
+------+------+
3 rows in set (0.02 sec)
为什么要这样做呢?
直接对目标表做去重、写入操作,这个过程不是原子的,因此我们通常会先将去重后的数据写入到一个临时表中,然后通过rename/mv操作对临时文件重命名,变成我们想要的目标文件,原先文件作废。这么做的原因是 rename/mv 操作是原子的。
函数 | 功能 |
---|---|
COUNT() | 统计符合条件的记录行数 |
SUM() | 计算某列数值的总和(仅适用于数值型列) |
AVG() | 计算某列数值的平均值(仅适用于数值型列) |
MAX() | 返回某列的最大值(支持数值、字符串、日期时间类型) |
MIN() | 返回某列的最小值(支持数值、字符串、日期时间类型) |
mysql> select * from students;
+----+-----+--------------+-------+
| id | sn | name | qq |
+----+-----+--------------+-------+
| 10 | 111 | 公孙离 | 12345 |
| 11 | 666 | 后羿 | 67890 |
| 20 | 333 | 貂蝉 | 34567 |
| 31 | 444 | 狄仁杰 | 56789 |
| 32 | 555 | 百里守约 | NULL |
+----+-----+--------------+-------+
5 rows in set (0.00 sec)
mysql> select count(*) from students;
+----------+
| count(*) |
+----------+
| 5 |
+----------+
1 row in set (0.03 sec)
mysql> select count(distinct math) from exam_result;
+----------------------+
| count(distinct math) |
+----------------------+
| 6 |
+----------------------+
1 row in set (0.00 sec)
mysql> select sum(chinese) from exam_result;
+--------------+
| sum(chinese) |
+--------------+
| 916 |
+--------------+
1 row in set (0.00 sec)
mysql> select avg(chinese + math + english) from exam_result;
+-------------------------------+
| avg(chinese + math + english) |
+-------------------------------+
| 323.5 |
+-------------------------------+
1 row in set (0.00 sec)
mysql> select max(english) from exam_result;
+--------------+
| max(english) |
+--------------+
| 90 |
+--------------+
1 row in set (0.01 sec)
mysql> select min(math) from exam_result where math > 80;
+-----------+
| min(math) |
+-----------+
| 90 |
+-----------+
1 row in set (0.00 sec)
在select中使用group by 子句可以对指定列进行分组查询。
select col1, col2, ... from table_name group by col;
本篇文章的分享就到这里了,如果您觉得在本文有所收获,还请留下您的三连支持哦~