一. 插入语句 — insert
语法:
insert into 表名 (需要插入的字段列表) values (第一行数据), (第二行数据), ... ,(第n行数据);
举例: 创建一张Student表,用来存储学生的身份信息:
id :代表学号,设为自增长的主键,不允许为空。name :学生姓名,不能为空。qq :学生的qq号,可以为空但不能重复。
mysql> create table if not exists Student(
-> id int unsigned primary key auto_increment,
-> name varchar(20) not null,
-> qq varchar(30) unique
-> );
Query OK, 0 rows affected (0.03 sec)
mysql> desc Student;
+-------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+------------------+------+-----+---------+----------------+
| id | int(10) unsigned | NO | PRI | NULL | auto_increment |
| name | varchar(20) | NO | | NULL | |
| qq | varchar(30) | YES | UNI | NULL | |
+-------+------------------+------+-----+---------+----------------+
3 rows in set (0.01 sec)
1. 指定 or 全字段插入
在插入时,我们可以在表名后括号中指定具体需要插入那个字段;如果不指定就默认是全字段的数据插入:
mysql> insert into Student (name, qq) values ('张三', '123456');
Query OK, 1 row affected (0.01 sec)
mysql> insert into Student values (20204912, '李四', '456789');
Query OK, 1 row affected (0.01 sec)
mysql> select * from Student;
+----------+--------+--------+
| id | name | qq |
+----------+--------+--------+
| 1 | 张三 | 123456 |
| 20204912 | 李四 | 456789 |
+----------+--------+--------+
2 rows in set (0.00 sec)
2. 多行数据插入
在插入时,我们可以在values后面进行多行数据的插入,每一个空格内就是一行数据,空格之间用逗号分隔:
mysql> insert into Student (name, qq) values ('朱五', '111111'), ('赵六', '222222');
Query OK, 2 rows affected (0.00 sec)
Records: 2 Duplicates: 0 Warnings: 0
mysql> select * from Student;
+----------+--------+--------+
| id | name | qq |
+----------+--------+--------+
| 1 | 张三 | 123456 |
| 20204912 | 李四 | 456789 |
| 20204913 | 朱五 | 111111 |
| 20204914 | 赵六 | 222222 |
+----------+--------+--------+
4 rows in set (0.00 sec)
3. key不冲突直接插入,冲突的话就修改
在插入时经常会出现由于主键或者唯一键对应的值已经存在而导致的插入失败,插入失败后我们又要删除该行重新插入。对此,我们在insert插入时配合使用on duplicate key 可以完成没有key冲突时正常插入;有key冲突时进行数据更新的工作,具体语法如下:
insert into ... on duplicate key update 字段1=更新后的值,...,字段n=更新后的值;
下面依然以Stdent表做演示,注意Student表中的id字段是主键、qq字段是唯一键,而name就是一个普通的字段。
0 row affected :表中有冲突的主键或唯一键,但冲突数据的值和update的值相等
mysql> select * from Student;
+----------+--------+--------+
| id | name | qq |
+----------+--------+--------+
| 1 | 张三 | 123456 |
| 20204912 | 李四 | 456789 |
| 20204913 | 朱五 | 111111 |
| 20204914 | 赵六 | 222222 |
+----------+--------+--------+
4 rows in set (0.00 sec)
mysql> insert into Student values (1, '张三', '123456')
-> on duplicate key update name='张三';
Query OK, 0 rows affected (0.00 sec)
mysql> select * from Student;
+----------+--------+--------+
| id | name | qq |
+----------+--------+--------+
| 1 | 张三 | 123456 |
| 20204912 | 李四 | 456789 |
| 20204913 | 朱五 | 111111 |
| 20204914 | 赵六 | 222222 |
+----------+--------+--------+
4 rows in set (0.00 sec)
1 row affected :表中没有冲突的主键或唯一键,数据被插入
mysql> select * from Student;
+----------+--------+--------+
| id | name | qq |
+----------+--------+--------+
| 1 | 张三 | 123456 |
| 20204912 | 李四 | 456789 |
| 20204913 | 朱五 | 111111 |
| 20204914 | 赵六 | 222222 |
+----------+--------+--------+
4 rows in set (0.00 sec)
mysql> insert into Student values (2, '王二麻子', '333333')
-> on duplicate key update name='王二麻子2';
Query OK, 1 row affected (0.00 sec)
mysql> select * from Student;
+----------+--------------+--------+
| id | name | qq |
+----------+--------------+--------+
| 1 | 张三 | 123456 |
| 2 | 王二麻子 | 333333 |
| 20204912 | 李四 | 456789 |
| 20204913 | 朱五 | 111111 |
| 20204914 | 赵六 | 222222 |
+----------+--------------+--------+
5 rows in set (0.00 sec)
2 row affected :表中有冲突的主键或唯一键,并且数据已经被更新
mysql> select * from Student;
+----------+--------------+--------+
| id | name | qq |
+----------+--------------+--------+
| 1 | 张三 | 123456 |
| 2 | 王二麻子 | 333333 |
| 20204912 | 李四 | 456789 |
| 20204913 | 朱五 | 111111 |
| 20204914 | 赵六 | 222222 |
+----------+--------------+--------+
5 rows in set (0.00 sec)
mysql> insert into Student values (1, '张三', '123456')
-> on duplicate key update name='木头老七', qq='444444';
Query OK, 2 rows affected (0.00 sec)
mysql> select * from Student;
+----------+--------------+--------+
| id | name | qq |
+----------+--------------+--------+
| 1 | 木头老七 | 444444|
| 2 | 王二麻子 | 333333 |
| 20204912 | 李四 | 456789 |
| 20204913 | 朱五 | 111111 |
| 20204914 | 赵六 | 222222 |
+----------+--------------+--------+
5 rows in set (0.00 sec)
4. 替换 ---- replace
replace相当于insert和duplicate语句结合使用封装出来的一个新SQL语句,它有如下特点:
1 row affected :主键 或者 唯一键 没有冲突,则直接插入。2 row affected :主键 或者 唯一键 如果冲突,则删除后再插入。
PS:没有0 row affected的情况了,如果替换数据一模一样的已经存在则归于2 row affected 的情况。总结起来就是主键或唯一键冲突就删除重新插入,不冲突的话直接插入。
语法:
replace into 表名 (字段列表) values (第一行数据),...,(第n行数据);
举例:
mysql> select * from Student;
+----------+--------------+--------+
| id | name | qq |
+----------+--------------+--------+
| 1 | 木头老七 | 444444 |
| 2 | 王二麻子 | 333333 |
| 20204912 | 李四 | 456789 |
| 20204913 | 朱五 | 111111 |
| 20204914 | 赵六 | 222222 |
+----------+--------------+--------+
5 rows in set (0.00 sec)
mysql> replace into Student values (1, '木头老七', '444444');
Query OK, 2 rows affected (0.01 sec)
mysql> replace into Student values (1, '公孙离', '444444');
Query OK, 2 rows affected (0.01 sec)
mysql> replace into Student values (3, '诸葛亮', '55555');
Query OK, 1 row affected (0.01 sec)
mysql> select * from Student;
+----------+--------------+--------+
| id | name | qq |
+----------+--------------+--------+
| 1 | 公孙离 | 444444 |
| 2 | 王二麻子 | 333333 |
| 3 | 诸葛亮 | 55555 |
| 20204912 | 李四 | 456789 |
| 20204913 | 朱五 | 111111 |
| 20204914 | 赵六 | 222222 |
+----------+--------------+--------+
6 rows in set (0.00 sec)
二. 查询语句 — select
select语句可以完成表数据的具体查询,搭配筛选语句使得select的查询更加灵活。
为了方便举例,在这里新建一张学生成绩表,下面的所有文字内容统一使用这张表。它包括如下5个字段:
id :学生的学号,设为自增长的主键。name :学生姓名,不允许为空。chinese :语文成绩,可以为空,默认0.0分。math :数学成绩,可以为空,默认0.0分。english :英语成绩,可以为空,默认0.0分。
mysql> create table if not exists TestScores(
-> id int unsigned primary key auto_increment,
-> name varchar(20) not null,
-> chinese float default 0.0,
-> math float default 0.0,
-> english float default 0.0
-> );
Query OK, 0 rows affected (0.02 sec)
mysql> desc TestScores;
+---------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------+------------------+------+-----+---------+----------------+
| id | int(10) 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 into TestScores(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);
Query OK, 7 rows affected (0.01 sec)
Records: 7 Duplicates: 0 Warnings: 0
1. 全字段查询
语法:
select * from 表名;
说明:
- 这里 * 号的作用类似于Linux命令的通配符,表示全部的意思。
- 通常情况下不建议使用 * 进行全列查询,原因如下:
- 查询的列越多,意味着需要传输的数据量越大。
- 可能会影响到索引的使用。
举例: 查询TestCsores表中所有字段的数据:
mysql> select * from TestScores;
+----+-----------+---------+------+---------+
| 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)
2. 指定字段查询
我们也可以查询表中特定字段的数据,其中指定字段的顺序不需要按定义表的顺序来:
语法: select后面直接跟需要查询的字段即可,如果有多个就用逗号分隔且不用加括号。
举例: 查询TestScores表中学生的数学成绩:
mysql> select name, math from TestScores;
+-----------+------+
| name | math |
+-----------+------+
| 曹操 | 98 |
| 孙权 | 78 |
| 孙策 | 98 |
| 刘备 | 84 |
| 程咬金 | 85 |
| 孙尚香 | 73 |
| 诸葛亮 | 65 |
+-----------+------+
7 rows in set (0.00 sec)
3. 查询表达式结果
select还有计算表达式的功能:
mysql> select 1+1;
+-----+
| 1+1 |
+-----+
| 2 |
+-----+
1 row in set (0.00 sec)
这个表达式还可以是表中的字段组合而成:
mysql> select name, math, chinese, english, math+chinese+english from TestScores;
+-----------+------+---------+---------+----------------------+
| name | math | chinese | english | math+chinese+english |
+-----------+------+---------+---------+----------------------+
| 曹操 | 98 | 67 | 56 | 221 |
| 孙权 | 78 | 87 | 77 | 242 |
| 孙策 | 98 | 88 | 90 | 276 |
| 刘备 | 84 | 82 | 67 | 233 |
| 程咬金 | 85 | 55 | 45 | 185 |
| 孙尚香 | 73 | 70 | 78 | 221 |
| 诸葛亮 | 65 | 75 | 30 | 170 |
+-----------+------+---------+---------+----------------------+
7 rows in set (0.00 sec)
在表达式后面加上as还可以对表达式重命名:
mysql> select name, math, chinese, english, math+chinese+english as total from TestScores;
+-----------+------+---------+---------+-------+
| name | math | chinese | english | total |
+-----------+------+---------+---------+-------+
| 曹操 | 98 | 67 | 56 | 221 |
| 孙权 | 78 | 87 | 77 | 242 |
| 孙策 | 98 | 88 | 90 | 276 |
| 刘备 | 84 | 82 | 67 | 233 |
| 程咬金 | 85 | 55 | 45 | 185 |
| 孙尚香 | 73 | 70 | 78 | 221 |
| 诸葛亮 | 65 | 75 | 30 | 170 |
+-----------+------+---------+---------+-------+
7 rows in set (0.00 sec)
4. 查询结果去重
在表中,可能会包含重复值。这并不成问题,不过,有时您也许希望仅仅列出不同(distinct)的值,distinct关键字可以帮助我们完成去重工作。
语法:
select distinct 字段名称 from表名称;
举例:
mysql> select math from TestScores;
+------+
| math |
+------+
| 98 |
| 78 |
| 98 |
| 84 |
| 85 |
| 73 |
| 65 |
+------+
7 rows in set (0.00 sec)
mysql> select distinct math from TestScores;
+------+
| math |
+------+
| 98 |
| 78 |
| 84 |
| 85 |
| 73 |
| 65 |
+------+
6 rows in set (0.00 sec)
补充: 如果我们要求表中重复的数据只能有一份的话,应该怎么办呢?首先想到的是:删除表中的重复记录,那就需要先找到那些行重复了,然后逐一删除,这样做的成本太高了还容易出错。这里有个表较好的方法是先使用distinct查询出原表中去重后的数据,然后把这些数据全部插入到一张新表中,最后删除旧表。
第一步:创建一张和旧表一样结构但数据为空的新表,这里要用到like字句:
create table 新表名 like 旧表名;
第二步:下面是向新表中插入所有旧表去重后的查询结果的语句:
insert into 新表名 select * distinct from 旧表名;
三. 筛选字句 — where
1. 介绍
where子句用于规定选择的标准,通常需要搭配其他语句使用。下面的运算符可在 where子句中使用:
运算符 | 说明 |
---|
(>, >=, <, <=) | (大于、大于等于、小于、小于等于) | = | 等于,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) |
注意:在写SQL时,语(子)句之间用空格隔开,字段之间用逗号隔开。
2. 举例
1、查询英语不及格的同学及他的英语成绩 (<60)
mysql> select name, english from TestScores where english<60;
+-----------+---------+
| name | english |
+-----------+---------+
| 曹操 | 56 |
| 程咬金 | 45 |
| 诸葛亮 | 30 |
+-----------+---------+
3 rows in set (0.00 sec)
2、语文成绩在 [80, 90] 分的同学及他的语文成绩
mysql> select name, chinese from TestScores where chinese>=80 and chinese<=90;
+--------+---------+
| name | chinese |
+--------+---------+
| 孙权 | 87 |
| 孙策 | 88 |
| 刘备 | 82 |
+--------+---------+
3 rows in set (0.00 sec)
mysql> select name, chinese from TestScores where chinese between 80 and 90;
+--------+---------+
| name | chinese |
+--------+---------+
| 孙权 | 87 |
| 孙策 | 88 |
| 刘备 | 82 |
+--------+---------+
3 rows in set (0.00 sec)
3、数学成绩是 58 或者 59 或者 98 或者 99 分的同学及数学成绩
mysql> select name, math from TestScores where math=58 or math=59 or math=98 or math=99;
+--------+------+
| name | math |
+--------+------+
| 曹操 | 98 |
| 孙策 | 98 |
+--------+------+
2 rows in set (0.00 sec)
mysql> select name, math from TestScores where math in (58, 59, 98, 99);
+--------+------+
| name | math |
+--------+------+
| 曹操 | 98 |
| 孙策 | 98 |
+--------+------+
2 rows in set (0.00 sec)
4、查询姓孙的同学 及 孙某同学
mysql> select name from TestScores where name like '孙%';
+-----------+
| name |
+-----------+
| 孙权 |
| 孙策 |
| 孙尚香 |
+-----------+
3 rows in set (0.00 sec)
mysql> select name from TestScores where name like '孙_';
+--------+
| name |
+--------+
| 孙权 |
| 孙策 |
+--------+
2 rows in set (0.00 sec)
5、语文成绩好于英语成绩的同学
mysql> select name, chinese, english from TestScores where chinese > english;
+-----------+---------+---------+
| name | chinese | english |
+-----------+---------+---------+
| 曹操 | 67 | 56 |
| 孙权 | 87 | 77 |
| 刘备 | 82 | 67 |
| 程咬金 | 55 | 45 |
| 诸葛亮 | 75 | 30 |
+-----------+---------+---------+
5 rows in set (0.00 sec)
6、查询语文成绩比英语成绩好30分以上的同学
mysql> select name, chinese, english from TestScores where chinese > english+30;
+-----------+---------+---------+
| name | chinese | english |
+-----------+---------+---------+
| 诸葛亮 | 75 | 30 |
+-----------+---------+---------+
1 row in set (0.00 sec)
7、总分在 200 分以下的同学 注意where字句中只能识别表的字段,但不能识别表达式的别名,因为where字句是和select查询同步进行的,查询完成之后才会进行表达式的计算。
mysql> select name, chinese+math+english as total from TestScores where total < 200;
ERROR 1054 (42S22): Unknown column 'total' in 'where clause'
mysql> select name, chinese+math+english as total from TestScores where chinese+math+english < 200;
+-----------+-------+
| name | total |
+-----------+-------+
| 程咬金 | 185 |
| 诸葛亮 | 170 |
+-----------+-------+
2 rows in set (0.00 sec)
8、语文成绩 > 80 并且不姓孙的同学 AND与NOT一起使用即可:
mysql> select name, chinese from TestScores where chinese>80 and not name like '孙%';
+--------+---------+
| name | chinese |
+--------+---------+
| 刘备 | 82 |
+--------+---------+
1 row in set (0.00 sec)
9、孙某同学,否则要求总成绩 > 200 并且 语文成绩 < 数学成绩 并且 英语成绩 > 80
mysql> select name, chinese, math, english, chinese+math+english as total from TestScores
-> where name like '孙%'
-> or (chinese+math+english > 200 and chinese < math and english > 80);
+-----------+---------+------+---------+-------+
| name | chinese | math | english | total |
+-----------+---------+------+---------+-------+
| 孙权 | 87 | 78 | 77 | 242 |
| 孙策 | 88 | 98 | 90 | 276 |
| 孙尚香 | 70 | 73 | 78 | 221 |
+-----------+---------+------+---------+-------+
3 rows in set (0.00 sec)
10、NULL 的查询 NULL其他数据比较时:
- =下的NULL是不安全的,比较结果全是NULL。
- <=>下的NULL是安全的,比较结果符合逻辑。
对于!=和<>而言,NULL都是不安全的。所以涉及到NULL的比较时,尽量用<=>,如果要比较不等于的话,在<=>前面加个not即可:
四. 排序字句 — order by
1. 介绍
ORDER BY 语句用于根据指定的列对结果集进行排序,且该语句默认按照升序对记录进行排序,当然我们也可以显示指定排序的方式:
asc :即ascending,为升序(从小到大)。desc :即descending,为降序(从大到小)。
PS:在MySQL中,NULL视为比任何值都小。
2. 举例
1、查询同学及数学成绩,按数学成绩升序显示
mysql> select name, math from TestScores;
+-----------+------+
| name | math |
+-----------+------+
| 曹操 | 98 |
| 孙权 | 78 |
| 孙策 | 98 |
| 刘备 | 84 |
| 程咬金 | 85 |
| 孙尚香 | 73 |
| 诸葛亮 | 65 |
+-----------+------+
7 rows in set (0.00 sec)
mysql> select name, math from TestScores order by math;
+-----------+------+
| name | math |
+-----------+------+
| 诸葛亮 | 65 |
| 孙尚香 | 73 |
| 孙权 | 78 |
| 刘备 | 84 |
| 程咬金 | 85 |
| 曹操 | 98 |
| 孙策 | 98 |
+-----------+------+
7 rows in set (0.00 sec)
mysql> select name, math from TestScores order by math asc;
+-----------+------+
| name | math |
+-----------+------+
| 诸葛亮 | 65 |
| 孙尚香 | 73 |
| 孙权 | 78 |
| 刘备 | 84 |
| 程咬金 | 85 |
| 曹操 | 98 |
| 孙策 | 98 |
+-----------+------+
7 rows in set (0.00 sec)
2、查询同学各门成绩,依次按 数学降序,英语升序,语文升序的方式显示 多字段排序时,排序优先级随order by后面的书写顺序而定:
mysql> select name, math, english, chinese from TestScores
-> order by math desc, english, chinese;
+-----------+------+---------+---------+
| name | math | english | chinese |
+-----------+------+---------+---------+
| 曹操 | 98 | 56 | 67 |
| 孙策 | 98 | 90 | 88 |
| 程咬金 | 85 | 45 | 55 |
| 刘备 | 84 | 67 | 82 |
| 孙权 | 78 | 77 | 87 |
| 孙尚香 | 73 | 78 | 70 |
| 诸葛亮 | 65 | 30 | 75 |
+-----------+------+---------+---------+
7 rows in set (0.00 sec)
3、查询同学及总分,由高到低 与where字句不同的是,order by子句中可以使用表达式或字段的别名,因为它们组合使用时的执行逻辑如下:
- 先根据where字句给出的条件筛选出原表格中满足条件的数据。
- 依据这些筛选出来的数据完成表达式的计算和一些重命名工作。
- 然后执行order by字句对上面的数据进行排序。
- 最后执行limit分页(这个后面讲解)。
mysql> select name, chinese+math+english as total from TestScores
-> order by total desc;
+-----------+-------+
| name | total |
+-----------+-------+
| 孙策 | 276 |
| 孙权 | 242 |
| 刘备 | 233 |
| 曹操 | 221 |
| 孙尚香 | 221 |
| 程咬金 | 185 |
| 诸葛亮 | 170 |
+-----------+-------+
7 rows in set (0.00 sec)
4、查询姓孙的同学或者姓曹的同学数学成绩,结果按数学成绩由高到低显示 结合 where子句和order by子句,注意它们的执行顺序:要先筛选然后才能排序:
mysql> select name, math from TestScores
-> where name like '孙%' or name like '曹%'
-> order by math desc;
+-----------+------+
| name | math |
+-----------+------+
| 曹操 | 98 |
| 孙策 | 98 |
| 孙权 | 78 |
| 孙尚香 | 73 |
+-----------+------+
4 rows in set (0.00 sec)
五. 分页字句 — limit
1. 配合查询时的介绍
SELECT ... FROM 表名 [WHERE ...] [ORDER BY ...] LIMIT n;
- 从s开始,筛选n条结果(用法类似于std::string::substr(…)):
SELECT ... FROM 表名 [WHERE ...] [ORDER BY ...] LIMIT s, n;
- 从s开始,筛选n条结果,比第二种用法更明确,建议使用(其中offset是偏移量的意思):
SELECT ... FROM 表名 [WHERE ...] [ORDER BY ...] LIMIT n OFFSET s;
使用建议:对未知表进行查询时,最好加一条limit 1 来先观察表的基本数据和结构;避免因为表中数据过多,查询全表数据导致数据库卡死。
2. 举例
按 id 进行分页,每页 3 条记录,然后分别显示 第 1、2、3 页:
mysql> select name, chinese, math, english from TestScores limit 0, 3;
+--------+---------+------+---------+
| name | chinese | math | english |
+--------+---------+------+---------+
| 曹操 | 67 | 98 | 56 |
| 孙权 | 87 | 78 | 77 |
| 孙策 | 88 | 98 | 90 |
+--------+---------+------+---------+
3 rows in set (0.00 sec)
mysql> select name, math, english from TestScores limit 3, 3;
+-----------+------+---------+
| name | math | english |
+-----------+------+---------+
| 刘备 | 84 | 67 |
| 程咬金 | 85 | 45 |
| 孙尚香 | 73 | 78 |
+-----------+------+---------+
3 rows in set (0.00 sec)
mysql> select name, math, english from TestScores limit 6, 3;
+-----------+------+---------+
| name | math | english |
+-----------+------+---------+
| 诸葛亮 | 65 | 30 |
+-----------+------+---------+
1 row in set (0.01 sec)
PS:这种分页且每页固定有n条数据的场景还是很常见的,比如我们在搜索引擎上搜索一个关键字时,整个页面就是一种分页的结果显示出来的:
六. 修改语句 — update
1. 介绍
update使用时通常需要结合where字句去筛选出特定的某一行数据然后再对其中的某个字段的值做修改;如果不筛选的话,默认修改的的是整个表格的数据。
语法:
update 表名称 set 列名称=新值 where 列名称=某值;
PS:为了更灵活筛选,update还可以配合where、order by和limit一起使用,具体看下面的例子。
2. 举例
1、将曹操同学的语文成绩变更为 80 分
mysql> select name, chinese from TestScores where name='曹操';
+--------+---------+
| name | chinese |
+--------+---------+
| 曹操 | 67 |
+--------+---------+
1 row in set (0.00 sec)
mysql> update TestScores set chinese=80 where name='曹操';
Query OK, 1 row affected (0.01 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> select name, chinese from TestScores where name='曹操';
+--------+---------+
| name | chinese |
+--------+---------+
| 曹操 | 80 |
+--------+---------+
1 row in set (0.00 sec)
2、将曹操同学的数学成绩变更为 60 分,语文成绩变更为 70 分
mysql> select name, math, chinese from TestScores where name='曹操';
+--------+------+---------+
| name | math | chinese |
+--------+------+---------+
| 曹操 | 98 | 80 |
+--------+------+---------+
1 row in set (0.00 sec)
mysql> update TestScores set math=60, chinese=70 where name='曹操';
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> select name, math, chinese from TestScores where name='曹操';
+--------+------+---------+
| name | math | chinese |
+--------+------+---------+
| 曹操 | 60 | 70 |
+--------+------+---------+
1 row in set (0.00 sec)
3、将总成绩倒数前三的 3 位同学的数学成绩加上 30 分 PS:数据更新,不支持 math += 30 这种语法,只能math = math + 30。
mysql> select name, math from TestScores order by chinese+math+english limit 3;
+-----------+------+
| name | math |
+-----------+------+
| 诸葛亮 | 65 |
| 程咬金 | 85 |
| 曹操 | 60 |
+-----------+------+
3 rows in set (0.00 sec)
mysql> update TestScores 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 from TestScores where name in ('诸葛亮', '程咬金', '曹操');
+-----------+------+
| name | math |
+-----------+------+
| 曹操 | 90 |
| 程咬金 | 115 |
| 诸葛亮 | 95 |
+-----------+------+
3 rows in set (0.00 sec)
七. 删除语句 — delete
1. 介绍
delete语句用于删除表中的行数据。
具体要删除那一行,可以通过where、order by、limit等字句筛选出来,语法如下:
delete from 表名称 where 列名称=值;
2. 举例
1、删除曹操同学的考试成绩
mysql> select name from TestScores where name='曹操';
+--------+
| name |
+--------+
| 曹操 |
+--------+
1 row in set (0.00 sec)
mysql> delete from TestScores where name='曹操';
Query OK, 1 row affected (0.01 sec)
mysql> select name from TestScores where name='曹操';
Empty set (0.00 sec)
3. 清空表数据
为了测试清空表的操作,我们成建一张测试表ForDelete用来举例:
mysql> create table if not exists ForDelete(
-> id int unsigned primary key auto_increment,
-> name varchar(20)
-> );
Query OK, 0 rows affected (0.03 sec)
mysql> desc ForDelete;
+-------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+------------------+------+-----+---------+----------------+
| id | int(10) unsigned | NO | PRI | NULL | auto_increment |
| name | varchar(20) | YES | | NULL | |
+-------+------------------+------+-----+---------+----------------+
2 rows in set (0.00 sec)
接下来向表中,插入三行数据:
mysql> insert into ForDelete (name) values ('a'), ('b'), ('c');
Query OK, 3 rows affected (0.01 sec)
Records: 3 Duplicates: 0 Warnings: 0
mysql> select * from ForDelete;
+----+------+
| id | name |
+----+------+
| 1 | a |
| 2 | b |
| 3 | c |
+----+------+
3 rows in set (0.01 sec)
接下来介绍两种清空表数据的方法。
方法一:delete from 表名
mysql> delete from ForDelete;
Query OK, 3 rows affected (0.00 sec)
mysql> insert into ForDelete (name) values ('d'), ('e'), ('f');
Query OK, 3 rows affected (0.00 sec)
Records: 3 Duplicates: 0 Warnings: 0
mysql> select * from ForDelete;
+----+------+
| id | name |
+----+------+
| 4 | d |
| 5 | e |
| 6 | f |
+----+------+
3 rows in set (0.00 sec)
使用delete情况表数据之后,发现重新插入的数据它的自增长值依然是在原来基础上递增的,说明delete清空表并没有清除自增长的记录值。我们查看该表的创建语句,发现确实还记录着auto_increment的值: 方法二:truncate table 表名 truncate 有截断的意思,该语句有如下三点需要注意:
- 只能对整表操作,不能像 DELETE 一样针对部分数据操作。
- 截断时 MySQL 不对数据操作,所以比 DELETE 更快,但是TRUNCATE在删除数据的时候,并不经过真正的事物,所以无法回滚。
- 该操作会重置表的 AUTO_INCREMENT 项。
举例:还是上面的测试表ForDelete,这次我们使用truncate来清空表的数据。
mysql> select * from ForDelete;
+----+------+
| id | name |
+----+------+
| 4 | d |
| 5 | e |
| 6 | f |
+----+------+
3 rows in set (0.00 sec)
mysql> truncate table ForDelete;
Query OK, 0 rows affected (0.05 sec)
mysql> select * from ForDelete;
Empty set (0.00 sec)
还是一样的,向这个已经被清空的表中重新插入三组数据,观察自增长值是怎么分配的:
mysql> insert into ForDelete (name) values ('g'), ('h'), ('i');
Query OK, 3 rows affected (0.01 sec)
Records: 3 Duplicates: 0 Warnings: 0
mysql> select * from ForDelete;
+----+------+
| id | name |
+----+------+
| 1 | g |
| 2 | h |
| 3 | i |
+----+------+
3 rows in set (0.00 sec)
观察新插入的三行数据,发现原来表的自增长值被重置了。最后我们还可以来看看该表的创建语句是否还记录着auto_increment的值:
八. DML使用总结
- 语(子)句之间用空格隔开,字段和()之间用逗号隔开。
- 查询时的执行顺序:where子句 + 其他语句 —> 表达式计算+重命名 —> order by字句 —> limit字句。
- where字句中不能识别重命名,其他字句可以。
|