【MySQL】(4)表的增删改查

文章目录
- 表的增删改查
- Create
-
- INSERT
- 插入重复时更新
- 替换
- Retrieve
-
- SELECT
-
- select执行顺序(重要)
- 全列查询 指定列查询
- 查询字段为表达式
- where条件
- 排序
- 筛选分页结果
- Update
- Delete
-
- delete
- 截断表
- 插入查询结果
表的增删改查
CRUD:Create(创建),Retrieve(读取),Update(更新),Delete(删除)
Create
INSERT
语法:
INSERT [INTO] 表名 [(列1, 列2, 列3, ...)]
VALUES (值1, 值2, 值3, ...),(值1, 值2, 值3, ...),(值1, 值2, 值3, ...),... ;
INTO 可以省略
(列1, 列2, 列3, ...) 指定要插入的列,(值1, 值2, 值3, ...) 与指定的列一一对应
列名列表可以省略,如果省略,则等价于全列插入,下面插入数据时要按照顺序给所有列指定一个值或 null。
插入重复时更新
由于主键或唯一键的存在,插入重复的值会导致插入失败
我们可以让插入改为更新操作。类似于 C++ unordered_map 的 operator[],键不存在则插入新键值对,键存在则更新值。
语法:
INSERT [INTO] 表名 [(列1, 列2, 列3, ...)] VALUES (值1, 值2, 值3, ...)
ON DUPLICATE KEY UPDATE 列1=新值1, 列2=新值2, 列3=新值3, ...;
其中,表名 是要插入数据的表名,列1, 列2, 列3, ... 是要插入数据的列名,值1, 值2, 值3, ... 是对应列的值。如果插入数据时出现了键冲突,即已有相同的主键或唯一键,则会执行 ON DUPLICATE KEY UPDATE 后面的语句来更新相应的数据。
例:
向名为 students 的表中插入一条记录,包含学生的学号、姓名和年龄信息,如果已经存在相同的学号,则将更新对应的姓名和年龄信息:
INSERT INTO students (id, name, age)
VALUES (1001, '张三', 20)
ON DUPLICATE KEY UPDATE name='张三', age=20;
其中,id 列为主键,如果已存在学号为 1001 的记录,则会将该记录的 name 列和 age 列更新为 '张三' 和 20。如果该学号不存在,则会插入一条新的记录,包含学号为 1001,姓名为 '张三',年龄为 20 的信息。
使用这个语句,可能会有三种返回结果:
0 rows affected表中有冲突数据,但更新的值与旧值相等1 row affected表中没有冲突数据,数据插入2 rows affected表中有冲突数据,数据更新
数据更新是两行受影响,这是因为更新数据分为两步,1.删除旧数据 2.插入新数据
替换
在 MySQL 中,替换数据可以使用 REPLACE 关键字。REPLACE 的作用是:如果表中存在指定的主键或唯一索引,则替换该行数据;如果不存在,则插入新的数据。
语法:
REPLACE INTO 表名 (列1, 列2, 列3, ...) VALUES (值1, 值2, 值3, ...);
使用这个语句,可能会有以下返回结果:
1 row affected表中没有冲突数据,数据插入2 rows affected表中有冲突数据,数据更新
注意:
REPLACE 是删除冲突行后插入,有时候冲突行不止一个,比如有多个唯一键的情况,那么 MySQL 会将所有冲突的行都删除,最后插入一条新数据。
Retrieve
SELECT
SELECT 语句是 MySQL 中最常用的语句之一,用于从一个或多个表中查询数据。
语法:
SELECT [DISTINCT] select_list
[FROM table_list]
[WHERE where_condition]
[GROUP BY grouping_columns]
[HAVING having_condition]
[ORDER BY ordering_columns [ASC|DESC], ...]
[LIMIT limit_number]
DISTINCT是 MySQL 中用于去重的关键字,它可以用于查询中的SELECT语句,用于去除查询结果中重复的行。select_list是要查询的列的列表,用逗号分隔。可以使用通配符*来查询所有列。也可以在查询中使用函数和表达式来生成新的列。table_list是要查询的表的列表,用逗号分隔。可以使用子查询来查询多个表中的数据。WHERE子句用于指定查询条件,它可以包含一个或多个表达式,用逻辑运算符(如 AND、OR、NOT)组合。可以使用比较运算符(如 =、<、>、<=、>=、<>)和其他运算符(如 LIKE、IN、BETWEEN)来构建条件。GROUP BY子句用于将查询结果按照指定的列进行分组,通常与聚合函数一起使用。HAVING子句用于指定分组后的条件,通常用于对聚合函数的结果进行过滤。ORDER BY子句用于指定查询结果的排序顺序,可以按照一个或多个列进行排序,并可以指定每个列的排序方式(升序或降序)。LIMIT子句用于限制查询结果的行数,可以指定一个或两个参数。第一个参数指定要返回的行数,第二个参数指定从哪一行开始返回结果。
注意:
使用多个可选项时要按照顺序写,比如 FROM 语句就是应该写在 WHERE 前面,不能写反
select执行顺序(重要)
在 SQL 中,SELECT 语句的执行顺序通常可以分为以下几个步骤:
FROM子句:从指定的表格中获取数据;JOIN子句:如果使用了JOIN操作,则将多个表格中的数据进行关联;(涉及多表查询,后面讲)WHERE子句:根据指定的条件过滤出符合要求的数据;GROUP BY子句:按照指定的列对数据进行分组;HAVING子句:对分组后的数据进行条件过滤;SELECT子句:选择要显示的列;DISTINCT子句:去除重复的数据;ORDER BY子句:按照指定的列对数据进行排序;LIMIT子句:限制查询结果的行数。
这里需要重点关注一下 select 和 distinct 子句执行是在 having 之后,order by 之前,这和我们语句的书写顺序是不一致的。
全列查询 指定列查询
建表
CREATE TABLE student_scores (id INT PRIMARY KEY AUTO_INCREMENT,name VARCHAR(50) NOT NULL,chinese INT,math INT,english INT
);
插入数据
INSERT INTO student_scores (name, chinese, math, english) VALUES('Alice', 80, 85, 90),('Bob', 75, 80, 85),('Charlie', 90, 95, 85),('Dave', 85, 90, 90),('Emma', 95, 85, 90),('Frank', 70, 75, 80);
全列查询
MariaDB [test_db]> select * from student_scores;
+----+---------+---------+------+---------+
| id | name | chinese | math | english |
+----+---------+---------+------+---------+
| 1 | Alice | 80 | 85 | 90 |
| 2 | Bob | 75 | 80 | 85 |
| 3 | Charlie | 90 | 95 | 85 |
| 4 | Dave | 85 | 90 | 90 |
| 5 | Emma | 95 | 85 | 90 |
| 6 | Frank | 70 | 75 | 80 |
+----+---------+---------+------+---------+
6 rows in set (0.00 sec)
指定列查询
MariaDB [test_db]> select id, name from student_scores;
+----+---------+
| id | name |
+----+---------+
| 1 | Alice |
| 2 | Bob |
| 3 | Charlie |
| 4 | Dave |
| 5 | Emma |
| 6 | Frank |
+----+---------+
6 rows in set (0.00 sec)
查询字段为表达式
直接使用 select 计算表达式
MariaDB [test_db]> select 2*3+1;
+-------+
| 2*3+1 |
+-------+
| 7 |
+-------+
1 row in set (0.00 sec)
查询字段为字段表达式,如下,计算所有学生语文成绩+5分后的结果
MariaDB [test_db]> select id, name, chinese+5 from student_scores;
+----+---------+-----------+
| id | name | chinese+5 |
+----+---------+-----------+
| 1 | Alice | 85 |
| 2 | Bob | 80 |
| 3 | Charlie | 95 |
| 4 | Dave | 90 |
| 5 | Emma | 100 |
| 6 | Frank | 75 |
+----+---------+-----------+
6 rows in set (0.00 sec)
查询每个人的总分
MariaDB [test_db]> SELECT name, chinese + math + english AS total_score-> FROM student_scores;
+---------+-------------+
| name | total_score |
+---------+-------------+
| Alice | 255 |
| Bob | 240 |
| Charlie | 270 |
| Dave | 265 |
| Emma | 270 |
| Frank | 225 |
+---------+-------------+
6 rows in set (0.00 sec)
AS 是用来为查询结果中的列指定别名的关键字。需要注意的是,使用 AS 关键字是可选的。在 SQL 中,也可以不使用 AS 关键字为列指定别名,直接在查询语句中给列起一个名称。例如:
MariaDB [test_db]> SELECT name, chinese + math + english total_score-> FROM student_scores;
这条语句和上面是等价的。
where条件
| 比较运算符 | 说明 |
|---|---|
>,>=,<,<= |
大于,大于等于,小于,小于等于 |
= |
等于,NULL 不安全,如 NULL = NULL 的结果是 NULL |
<=> |
等于,NULL 安全,如 NULL <=> NULL 的结果是 TRUE(1) |
!=,<> |
不等于,NULL != NULL 和 NULL <> NULL 的结果都是 NULL |
BETWEEN a AND b |
范围匹配,如果 a <= value <= b,则返回 TRUE(1) |
IN(option, ...) |
如果是 option 中的任意一个,返回 TRUE(1) |
IS NULL |
是 NULL |
IS NOT NULL |
不是 NULL |
LIKE |
模糊匹配,% 表示任意多个任意字符,_ 表示任意一个字符 |
| 逻辑运算符 | 说明 |
|---|---|
AND |
逻辑与 |
OR |
逻辑或 |
NOT |
逻辑非 |
在 SQL 中,NULL 表示缺失或未知的值,它不等于任何值,包括 NULL 本身。因此,NULL = NULL 的结果不是 TRUE,也不是 FALSE,而是 NULL。
这是因为 NULL 值的比较无法确定两个值是否相等,因此比较的结果也是未知的。在 SQL 中,任何未知的结果都被认为是 NULL,因此 NULL=NULL 的结果也是 NULL。
如果需要比较某个值是否为 NULL,可以使用 IS NULL 或 IS NOT NULL 进行判断。
例:
查询数学成绩大于等于90的记录
MariaDB [test_db]> select * from student_scores where math >= 90;
+----+---------+---------+------+---------+
| id | name | chinese | math | english |
+----+---------+---------+------+---------+
| 3 | Charlie | 90 | 95 | 85 |
| 4 | Dave | 85 | 90 | 90 |
+----+---------+---------+------+---------+
2 rows in set (0.00 sec)
向表中插入一行三科分数都为null的记录
MariaDB [test_db]> select * from student_scores;
+----+---------+---------+------+---------+
| id | name | chinese | math | english |
+----+---------+---------+------+---------+
| 1 | Alice | 80 | 85 | 90 |
| 2 | Bob | 75 | 80 | 85 |
| 3 | Charlie | 90 | 95 | 85 |
| 4 | Dave | 85 | 90 | 90 |
| 5 | Emma | 95 | 85 | 90 |
| 6 | Frank | 70 | 75 | 80 |
| 7 | God | NULL | NULL | NULL |
+----+---------+---------+------+---------+
7 rows in set (0.00 sec)
使用 chinese=null 找不到这条记录,因为任何值与 null 比较都返回 null
需要用 is null
MariaDB [test_db]> select * from student_scores where chinese=null;
Empty set (0.00 sec)
MariaDB [test_db]> select * from student_scores where chinese is null;
+----+------+---------+------+---------+
| id | name | chinese | math | english |
+----+------+---------+------+---------+
| 7 | God | NULL | NULL | NULL |
+----+------+---------+------+---------+
1 row in set (0.00 sec)
使用 between 选出数学成绩在80到90之间的信息
MariaDB [test_db]> select * from student_scores where math between 80 and 90;
+----+-------+---------+------+---------+
| id | name | chinese | math | english |
+----+-------+---------+------+---------+
| 1 | Alice | 80 | 85 | 90 |
| 2 | Bob | 75 | 80 | 85 |
| 4 | Dave | 85 | 90 | 90 |
| 5 | Emma | 95 | 85 | 90 |
+----+-------+---------+------+---------+
4 rows in set (0.00 sec)
使用 in() 判断
MariaDB [test_db]> select 1 in (1,2,3,4,5);
+------------------+
| 1 in (1,2,3,4,5) |
+------------------+
| 1 |
+------------------+
1 row in set (0.00 sec)MariaDB [test_db]> select -1 in (1,2,3,4,5);
+-------------------+
| -1 in (1,2,3,4,5) |
+-------------------+
| 0 |
+-------------------+
1 row in set (0.00 sec)
查询语文成绩为75或95的记录
MariaDB [test_db]> select * from student_scores where chinese in (75,95);
+----+------+---------+------+---------+
| id | name | chinese | math | english |
+----+------+---------+------+---------+
| 2 | Bob | 75 | 80 | 85 |
| 5 | Emma | 95 | 85 | 90 |
+----+------+---------+------+---------+
2 rows in set (0.00 sec)
也可以使用 OR 来连接多个判断语句
select * from student_scores where chinese=75 OR chinese=95;
这两个SQL语句是等价的。
使用模糊匹配查询名字里有字母a的记录
MariaDB [test_db]> select * from student_scores where name like '%a%';
+----+---------+---------+------+---------+
| id | name | chinese | math | english |
+----+---------+---------+------+---------+
| 1 | Alice | 80 | 85 | 90 |
| 3 | Charlie | 90 | 95 | 85 |
| 4 | Dave | 85 | 90 | 90 |
| 5 | Emma | 95 | 85 | 90 |
| 6 | Frank | 70 | 75 | 80 |
+----+---------+---------+------+---------+
5 rows in set (0.00 sec)
找出总分小于260的学生信息
MariaDB [test_db]> select id, name, chinese+math+english as total from student_scores where chinese+math+english < 260;
+----+-------+-------+
| id | name | total |
+----+-------+-------+
| 1 | Alice | 255 |
| 2 | Bob | 240 |
| 6 | Frank | 225 |
+----+-------+-------+
3 rows in set (0.00 sec)
有些人可能会这样写:
MariaDB [test_db]> select id, name, chinese+math+english as total from student_scores where total < 260;
ERROR 1054 (42S22): Unknown column 'total' in 'where clause'
这就是一个经典的错误,标准的零分。因为取别名的执行顺序在 where 语句之后,where 里面就开始写别名 MySQL 是不认识的。
查询名字里没有字母e,并且语文成绩大于70的同学
MariaDB [test_db]> select * from student_scores where name not like '%e%' and chinese > 70;
+----+------+---------+------+---------+
| id | name | chinese | math | english |
+----+------+---------+------+---------+
| 2 | Bob | 75 | 80 | 85 |
+----+------+---------+------+---------+
1 row in set (0.00 sec)
排序
按数学成绩升序排序
MariaDB [test_db]> select name, math from student_scores order by math;
+---------+------+
| name | math |
+---------+------+
| God | NULL |
| Frank | 75 |
| Bob | 80 |
| Alice | 85 |
| Emma | 85 |
| Dave | 90 |
| Charlie | 95 |
+---------+------+
7 rows in set (0.00 sec)
默认排序方式就是升序排序。
按数学成绩降序排序
MariaDB [test_db]> select name, math from student_scores order by math desc;
+---------+------+
| name | math |
+---------+------+
| Charlie | 95 |
| Dave | 90 |
| Alice | 85 |
| Emma | 85 |
| Bob | 80 |
| Frank | 75 |
| God | NULL |
+---------+------+
7 rows in set (0.01 sec)
指定排序方式 desc 即为降序排序
注
NULL 被视为最小值
按数学降序,英语升序,语文升序方式排序
MariaDB [test_db]> select * from student_scores order by math desc, english asc, chinese asc;
+----+---------+---------+------+---------+
| id | name | chinese | math | english |
+----+---------+---------+------+---------+
| 3 | Charlie | 90 | 95 | 85 |
| 4 | Dave | 85 | 90 | 90 |
| 1 | Alice | 80 | 85 | 90 |
| 5 | Emma | 95 | 85 | 90 |
| 2 | Bob | 75 | 80 | 85 |
| 6 | Frank | 70 | 75 | 80 |
| 7 | God | NULL | NULL | NULL |
+----+---------+---------+------+---------+
7 rows in set (0.00 sec)
多字段排序,各 字段 排序方式 之间用 , 分隔
按总分升序排序
MariaDB [test_db]> select id, name, chinese+math+english as total from student_scores order by total;
+----+---------+-------+
| id | name | total |
+----+---------+-------+
| 7 | God | NULL |
| 6 | Frank | 225 |
| 2 | Bob | 240 |
| 1 | Alice | 255 |
| 4 | Dave | 265 |
| 3 | Charlie | 270 |
| 5 | Emma | 270 |
+----+---------+-------+
7 rows in set (0.00 sec)
这里我们在 order by 里面使用别名就不会报错,原因是 select 选择显示列的执行在 order by 排序之前。
筛选分页结果
语法:
LIMIT [offset,] rows_count;LIMIT rows_count OFFSET offset;
其中,rows_count 表示要返回的行数,offset 表示从查询结果的哪一行开始返回(从 0 开始)。可以省略 offset 参数,此时默认从第一行开始返回,例如:
LIMIT 10:返回前 10 行数据;LIMIT 5, 10:从第 6 行开始返回,返回 10 行数据。- 也可以写成
LIMIT 10 OFFSET 5这两种写法是等价的
- 也可以写成
例:
查询总分排名前三的
MariaDB [test_db]> select id, name, chinese+math+english as total from student_scores order by total desc limit 3;
+----+---------+-------+
| id | name | total |
+----+---------+-------+
| 3 | Charlie | 270 |
| 5 | Emma | 270 |
| 4 | Dave | 265 |
+----+---------+-------+
3 rows in set (0.00 sec)
查询总分排名第四到第六的
MariaDB [test_db]> select id, name, chinese+math+english as total from student_scores order by total desc limit 3, 3;
+----+-------+-------+
| id | name | total |
+----+-------+-------+
| 1 | Alice | 255 |
| 2 | Bob | 240 |
| 6 | Frank | 225 |
+----+-------+-------+
3 rows in set (0.00 sec)
Update
语法:
UPDATE table_name
SET column1 = value1, column2 = value2, ...
[WHERE where_condition]
[ORDER BY ordering_columns [ASC|DESC], ...]
[LIMIT limit_number];
注意:
where 子句基本上是必写的,如果不写,所有记录都会被修改。
例:
将id为4的同学的语文成绩改为 80,英语成绩改为 95
SQL 语句如下:
update student_scores
set chinese=80,english=95
where id=4;
结果:
MariaDB [test_db]> update student_scores set chinese=80,english=95 where id=4;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0MariaDB [test_db]> select * from student_scores;
+----+---------+---------+------+---------+
| id | name | chinese | math | english |
+----+---------+---------+------+---------+
| 1 | Alice | 80 | 85 | 90 |
| 2 | Bob | 75 | 80 | 85 |
| 3 | Charlie | 90 | 95 | 85 |
| 4 | Dave | 80 | 90 | 95 |
| 5 | Emma | 95 | 85 | 90 |
| 6 | Frank | 70 | 75 | 80 |
| 7 | God | NULL | NULL | NULL |
+----+---------+---------+------+---------+
7 rows in set (0.00 sec)
将数学成绩倒数前三的同学的数学成绩+3分
update student_scores
set math=math+3
order by math
limit 3;
结果:
MariaDB [test_db]> select * from student_scores;
+----+---------+---------+------+---------+
| id | name | chinese | math | english |
+----+---------+---------+------+---------+
| 1 | Alice | 80 | 85 | 90 |
| 2 | Bob | 75 | 83 | 85 |
| 3 | Charlie | 90 | 95 | 85 |
| 4 | Dave | 80 | 90 | 95 |
| 5 | Emma | 95 | 85 | 90 |
| 6 | Frank | 70 | 78 | 80 |
| 7 | God | NULL | NULL | NULL |
+----+---------+---------+------+---------+
7 rows in set (0.00 sec)
Frank 和 Bob 的数学成绩加了 3 分,God 没有成绩,但 null 被视为最小值,成绩+3 还是 null。
Delete
delete
语法:
DELETE FROM table_name
[WHERE where_condition]
[ORDER BY ordering_columns [ASC|DESC], ...]
[LIMIT limit_number];
例:
删除 id 为 2 的学生记录
MariaDB [test_db]> delete from student_scores where id=2;
Query OK, 1 row affected (0.01 sec)MariaDB [test_db]> select * from student_scores;
+----+---------+---------+------+---------+
| id | name | chinese | math | english |
+----+---------+---------+------+---------+
| 1 | Alice | 80 | 85 | 90 |
| 3 | Charlie | 90 | 95 | 85 |
| 4 | Dave | 80 | 90 | 95 |
| 5 | Emma | 95 | 85 | 90 |
| 6 | Frank | 70 | 78 | 80 |
| 7 | God | NULL | NULL | NULL |
+----+---------+---------+------+---------+
6 rows in set (0.00 sec)
如果你想删除所有数据,可以不加 where 条件。
需要注意的是,DELETE 语句删除的数据不可恢复,因此在执行删除操作之前,一定要仔细确认。
截断表
截断表(TRUNCATE TABLE)是一种删除表中所有数据的快速方法。与 DELETE FROM 语句相比,使用 TRUNCATE TABLE 可以更快地清空表中的数据,并且不需要记录日志,因此它的执行速度更快。
语法:
TRUNCATE [TABLE] table_name;
插入查询结果
插入查询结果是指将一个 SELECT 查询的结果插入到另一个表中,也称为“插入选择”(INSERT INTO ... SELECT)。
语法:
INSERT INTO table_name [(column1, column2, column3, ...)]
SELECT column1, column2, column3, ...
FROM another_table
WHERE ...
其中,table_name 是要插入数据的目标表的名称,括号中的列名指定了要插入的列,可以省略。SELECT 查询语句用于查询要插入的数据,可以根据需要添加 WHERE 子句来筛选数据。查询结果中的列与目标表中的列一一对应,如果目标表中的列少于查询结果中的列,只会插入目标表中的列对应的数据。
需要注意的是,插入查询结果时,目标表的结构必须与查询结果的列数和数据类型一致,否则会发生插入失败或数据截断等错误。同时,插入查询结果时,如果目标表中已经存在与查询结果中的数据主键或唯一键冲突的行,将会插入失败。
例:
创建一个与 student_scores 结构相同的表
MariaDB [test_db]> create table student_scores_backup like student_scores;
Query OK, 0 rows affected (0.01 sec)
使用插入查询语句将 student_scores 表的数据插入到新表 student_scores_backup
MariaDB [test_db]> insert into student_scores_backup-> select * from student_scores;
Query OK, 6 rows affected (0.00 sec)
Records: 6 Duplicates: 0 Warnings: 0MariaDB [test_db]> select * from student_scores_backup;
+----+---------+---------+------+---------+
| id | name | chinese | math | english |
+----+---------+---------+------+---------+
| 1 | Alice | 80 | 85 | 90 |
| 3 | Charlie | 90 | 95 | 85 |
| 4 | Dave | 80 | 90 | 95 |
| 5 | Emma | 95 | 85 | 90 |
| 6 | Frank | 70 | 78 | 80 |
| 7 | God | NULL | NULL | NULL |
+----+---------+---------+------+---------+
6 rows in set (0.00 sec)
这样就完成了一个表的备份。


