阅读整理自《MySQL 必知必会》- 朱晓峰,详细内容请登录 极客时间 官网购买专栏。
添加数据
添加数据的语法结构:
insert into 表名 [(字段名 [,字段名] ...)]
values (值的列表);
添加数据分为两种情况:插入数据记录和插入查询结果。
测试数据
mysql> describe goodsmaster;
+---------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------------+--------------+------+-----+---------+----------------+
| barcode | text | YES | | NULL | |
| goodname | text | YES | | NULL | |
| price | decimal(5,2) | YES | | NULL | |
| itemnumber | int | NO | PRI | NULL | auto_increment |
| specification | text | YES | | NULL | |
| unit | text | YES | | NULL | |
+---------------+--------------+------+-----+---------+----------------+
6 rows in set (0.01 sec)
插入数据记录
这里只给3个字段赋值,itemnumber、specification、unit不赋值:
insert into demo.goodsmaster (barcode, goodsname, price) values ('0004', '测试', 10);
mysql> insert into demo.goodsmaster (itemnumber, barcode, goodname, specification, unit, price) values (4, '004', 'ruler', 'tangle', 'a', 0.5);
Query OK, 1 row affected (0.00 sec)
mysql> select * from demo.goodsmaster;
+---------+-----------------+-------+------------+---------------+------+
| barcode | goodname | price | itemnumber | specification | unit |
+---------+-----------------+-------+------------+---------------+------+
| 004 | ruler | 0.50 | 4 | tangle | a |
| 0004 | 测试 | 10.00 | 102 | NULL | NULL |
+---------+-----------------+-------+------------+---------------+------+
7 rows in set (0.00 sec)
在插入一条数据记录的时候,必须要考虑字段约束的 3 种情况:
-
如果字段允许为空,而我们没有给它赋值,那么 MySQL 会自动给它们赋予空值。
“specification”, "unit"字段都允许为空,因此如果数据插入语句没有指定这几个字段的值,MySQL 会自动插入空值
-
如果字段是主键,就不能为空,这个时候,MySQL 会按照添加的约束进行处理。比如字段"itemnumber"是主键,不能为空,而我们定义了自增约束,所以 MySQL 自动在之前的最大值基础上加了1。因此,itemnumber 也有了自己该有的值
-
如果有一个字段定义不能为空,又不是主键,当插入一条数据记录的时候,就必须给这个记录赋值
如果操作违反了字段的约束限制,会出现报错。
比如说,尝试把表 demo.goodsmaster 的字段 “speicification” 改为不能为空:
mysql> alter table goodsmaster modify specification text not null;
ERROR 1138 (22004): Invalid use of NULL value
表里已经有一条没有给字段"specification"赋值的数据记录,这跟给字段“specification”添加非空约束的操作冲突了,
要把字段“speicification”的值为空的数据记录删除,然后再修改字段约束:
mysql> delete from goodsmaster where specification is NULL;
Query OK, 1 row affected (0.01 sec)
删除数据记录之后,再运行上面的语句,给字段"specification"添加非空约束,就成功了:
mysql> alter table goodsmaster modify specification text not null;
Query OK, 0 rows affected (0.17 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> describe goodsmaster;
+---------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------------+--------------+------+-----+---------+----------------+
| barcode | text | YES | | NULL | |
| goodname | text | YES | | NULL | |
| price | decimal(5,2) | YES | | NULL | |
| itemnumber | int | NO | PRI | NULL | auto_increment |
| specification | text | NO | | NULL | |
| unit | text | YES | | NULL | |
+---------------+--------------+------+-----+---------+----------------+
6 rows in set (0.01 sec)
验证一下非空约束,尝试部分插入一条数据记录,不给字段 specification 赋值:
mysql> insert into demo.goodsmaster (barcode, goodname, price) values ('0004', '测试', 10);
ERROR 1364 (HY000): Field 'specification' doesn't have a default value
报错提示字段"specification"没有默认值,也就是说,这个字段不能为空,如果插入数据时不给它赋值,就必须给它一个默认值。
部分插入一条数据记录是可以的,但前提是,没有赋值的字段,一定要让 MySQL 知道如何处理,比如可以为空、有默认值,或者是自增约束字段,等等,否则,MySQL 会提示错误的。
插入查询结果
MySQL 支持把查询的结果插入到数据表中,可以指定字段,甚至是数值,插入到数据表中。语法结构如下:
insert into 表名 (字段名)
select 字段名或值
from 表名
where 条件
把一个查询结果插入数据表中的方式,可以提高添加数据的效率。
比如,历史流水表设计与流水表非常类似。不同的是,历史流水表增加了一些字段来标识历史流水的状态,比如日结时间字段,是用来记录日结操作是什么时候进行的。
insert into 历史流水表 (日结时间字段,其他字段)
select 获取当前时间函数,其他字段
from 流水表
删除数据
数据删除的语法很简单:
delete from 表名
where 条件
删除全部数据:
mysql> select * from demo.test1;
+------+-----------+-------+------------+
| bar | goodsname | price | itemnumber |
+------+-----------+-------+------------+
| 001 | book | 29.51 | 1 |
| 002 | pen | 5.17 | 2 |
| 003 | rubber | 2.42 | 3 |
+------+-----------+-------+------------+
3 rows in set (0.00 sec)
mysql> delete from demo.test1;
Query OK, 3 rows affected (0.01 sec)
mysql> select * from demo.test1;
Empty set (0.00 sec)
如果在 Workbench 中运行上面的 SQL 语句,会提示错误。因为 Workbench 自动处于安全模式,它要求对数据的删除或修改操作中必须包含 WHERE 条件。而且,这个 WHERE 条件中,必须用到主键约束或者唯一性约束的字段。MySQL 的这种安全性设置,主要就是为了防止删除或者修改数据时出现误操作,导致删除或修改了不相关的数据。
mysql> select * from demo.goodsmaster;
+---------+----------+-------+------------+---------------+------+
| barcode | goodname | price | itemnumber | specification | unit |
+---------+----------+-------+------------+---------------+------+
| 001 | book | 1.50 | 1 | book1 | a |
| 004 | ruler | 0.50 | 4 | tangle | a |
+---------+----------+-------+------------+---------------+------+
2 rows in set (0.00 sec)
mysql> delete from demo.goodsmaster where itemnumber>=1;
Query OK, 2 rows affected (0.01 sec)
mysql> select * from demo.goodsmaster;
Empty set (0.00 sec)
修改数据
数据修改语法:
update 表名
set 字段名=值
where 条件
不要修改主键字段的值。因为主键是数据记录的唯一标识,如果修改了主键的值,就有可能会破坏数据的完整性。
mysql> update demo.goodsmaster set price=2.5 where itemnumber=1;
Query OK, 1 row affected (0.01 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> select * from demo.goodsmaster;
+---------+----------+-------+------------+---------------+------+
| barcode | goodname | price | itemnumber | specification | unit |
+---------+----------+-------+------------+---------------+------+
| 001 | book | 2.50 | 1 | book1 | a |
+---------+----------+-------+------------+---------------+------+
1 row in set (0.00 sec)
查询数据
查询语句的语法结构:
select *|字段列表
from 数据源
where 条件
group by 字段
having 条件
order by 字段
limit 起始点,行数
- SELECT:是查询关键字,表示要做一个查询。
*
是一个通配符,表示要查询表中所有的字段。也可以把要查询的字段罗列出来,这样,查询的结果可以只显示想要查询的字段内容 - WHERE:表示查询条件。可以把要查询的数据所要满足的条件,放在 WHERE 关键字之后
- GROUP BY:表示查询结果要分组,经常与 MySQL 的聚合函数一起使用
- HAVING:用于筛选查询结果,跟 WHERE 类似
FROM
FROM 关键字表示查询的数据源。可以把要查询的数据表名,直接写在 FROM 关键字之后。在关联表中 FROM 关键字后面,还可以跟着更复杂的数据表联接。数据源也不一定是表,也可以是一个查询的结果。比如下面的查询:
mysql> select a.goodname, a.price from
-> (select * from demo.goodsmaster) as a;
+----------+-------+
| goodname | price |
+----------+-------+
| book | 2.50 |
+----------+-------+
1 row in set (0.00 sec)
select * from demo.goodsmaster
部分叫做派生表(derived table),或者子查询(subquery),意思是我们把一个查询结果数据集当做一个虚拟的数据表来看待。MySQL 规定,必须要用 AS 关键字给这个派生表起一个别名。在这张图中,给这个派生表起了个名字,叫做 a 。
ORDER BY
ORDER BY 的作用,是告诉 MySQL,查询结果如何排序。ASC 表示升序,DESC 表示降序。
mysql> select * from demo.goodsmaster;
+---------+----------+-------+------------+---------------+------+
| barcode | goodname | price | itemnumber | specification | unit |
+---------+----------+-------+------------+---------------+------+
| 001 | book | 2.50 | 1 | book1 | a |
| 002 | ruler | 1.00 | 104 | NULL | NULL |
| 003 | pen | 2.00 | 105 | NULL | NULL |
| 003 | pencil | 1.60 | 106 | NULL | NULL |
| 001 | notebook | 3.00 | 107 | NULL | NULL |
+---------+----------+-------+------------+---------------+------+
5 rows in set (0.00 sec)
mysql> select * from demo.goodsmaster order by barcode asc, price desc;
+---------+----------+-------+------------+---------------+------+
| barcode | goodname | price | itemnumber | specification | unit |
+---------+----------+-------+------------+---------------+------+
| 001 | notebook | 3.00 | 107 | NULL | NULL |
| 001 | book | 2.50 | 1 | book1 | a |
| 002 | ruler | 1.00 | 104 | NULL | NULL |
| 003 | pen | 2.00 | 105 | NULL | NULL |
| 003 | pencil | 1.60 | 106 | NULL | NULL |
+---------+----------+-------+------------+---------------+------+
5 rows in set (0.00 sec)
LIMIT
LIMIT 的作用是告诉 MySQL 只显示部分查询的结果。MySQL中,起始位置的起点是0。
mysql> select * from demo.goodsmaster limit 1,2;
+---------+----------+-------+------------+---------------+------+
| barcode | goodname | price | itemnumber | specification | unit |
+---------+----------+-------+------------+---------------+------+
| 002 | ruler | 1.00 | 104 | NULL | NULL |
| 003 | pen | 2.00 | 105 | NULL | NULL |
+---------+----------+-------+------------+---------------+------+
2 rows in set (0.00 sec)
这里的“LIMIT 1,2”中,“1”表示起始位置,1 表示从第 2 条记录开始;“2”表示 2 条数据。因此,“LIMIT 1,2”就表示从第 2 条数据开始,显示 2 条数据,也就是显示了第 2、3 条数据。
小结
insert into 表名 [(字段名 [,字段名] ...)] values (值的列表);
insert into 表名 (字段名)
select 字段名或值
from 表名
where 条件
delete from 表名
where 条件
update 表名
set 字段名=值
where 条件
select *|字段列表
from 数据源
where 条件
group by 字段
having 条件
order by 字段
limit 起始点,行数
如果把查询的结果插入到表中时,导致主键约束或者唯一性约束被破坏了,就可以用“ON DUPLICATE”关键字进行处理。这个关键字的作用是,告诉 MySQL,如果遇到重复的数据,该如何处理。
假设用户有 2 个各自独立的门店,分别有自己的系统。现在需要引入连锁经营的模式,把 2 个店用一套系统统一管理。那么首先遇到的问题就是,需要进行数据整合。
门店 A 的商品信息表是“demo.goods1”,代码如下:
mysql> select * from demo.goods1;
+------------+---------+-----------+---------------+---------+------------+
| itemnumber | barcode | goodsname | specification | unit | salesprice |
+------------+---------+-----------+---------------+---------+------------+
| 1 | 001 | book | 16k | a | 88.00 |
| 2 | 002 | pen | 10in | package | 10.00 |
| 3 | 003 | rubber | NULL | a | 2.00 |
+------------+---------+-----------+---------------+---------+------------+
3 rows in set (0.00 sec)
门店 B 的商品信息表是“demo.goods2”:
ysql> select * from demo.goods2;
+------------+---------+-----------+---------------+------+------------+
| itemnumber | barcode | goodsname | specification | unit | salesprice |
+------------+---------+-----------+---------------+------+------------+
| 1 | 001 | tech book | NULL | NULL | 66.00 |
| 4 | 004 | bread | NULL | NULL | 1.50 |
+------------+---------+-----------+---------------+------+------------+
2 rows in set (0.00 sec)
假设要把门店 B 的商品数据,插入到门店 A 的商品表中去,如果有重复的商品编号,就用门店 B 的条码,替换门店 A 的条码,用门店 B 的商品名称,替换门店 A 的商品名称;如果没有重复的编号,就直接把门店 B 的商品数据插入到门店 A 的商品表中。
mysql> insert into demo.goods1
-> select * from demo.goods2 as a
-> on duplicate key update barcode=a.barcode, goodsname=a.goodsname;
Query OK, 3 rows affected (0.01 sec)
Records: 2 Duplicates: 1 Warnings: 0
mysql> select * from demo.goods1;
+------------+---------+-----------+---------------+---------+------------+
| itemnumber | barcode | goodsname | specification | unit | salesprice |
+------------+---------+-----------+---------------+---------+------------+
| 1 | 001 | tech book | 16k | a | 88.00 |
| 2 | 002 | pen | 10in | package | 10.00 |
| 3 | 003 | rubber | NULL | a | 2.00 |
| 4 | 004 | bread | NULL | NULL | 1.50 |
+------------+---------+-----------+---------------+---------+------------+
4 rows in set (0.00 sec)
MySQL 数据插入:https://dev.mysql.com/doc/refman/8.0/en/insert.html
MySQL 数据更新:https://dev.mysql.com/doc/refman/8.0/en/update.html
MySQL 数据查询:https://dev.mysql.com/doc/refman/8.0/en/select.html