MySQL第三讲·SQL boy的CRUD操作

|----------------|
| 你好,我是安然无虞。 |

文章目录

增删查改:如何操作表中的数据?

关于SQL的CRUD操作是很重要的,有些公司面试的时候会要求我们写一些SQL,我上次面试字节的时候就遇到了(手动狗头)。

在我们的超市项目中,我们给用户设计好了一个数据库demo.goodsmaster,定义好了里面的字段以及各种约束,如下:

sql 复制代码
mysql> desc demo.goodsmaster;
+---------------+--------------+------+-----+---------+--+
| Field         | Type         | Null | Key | Default |Extra        |
+---------------+------------+------+-----+---------+------------+
| itemnumber    | int        | NO   | PRI | NULL    |auto_increment |
| barcode       | text       | NO   |     | NULL    |                |
| goodsname     | text       | NO   |     | NULL    |                |
| specification | text       | YES  |     | NULL    |                |
| unit          | text       | YES  |     | NULL    |                |
| price         | decimal(10,2)| NO   |     | NULL    |              |
+---------------+------------+------+-----+---------+----------------+
6 rows in set (0.02 sec)

OK,下面我们对这张表进行操作。

添加数据

首先添加数据的语法结构如下:

sql 复制代码
insert into 表名 [(字段名 [,字段名] ...)] values (值的列表);

这里的'[ ]'表示里面的内容可选,也就是说,根据MySQL的语法要求,写不写都可以。

添加数据分为两种情况:插入数据记录和插入查询结果。下面进行分别介绍:

插入数据记录

MySQL支持的数据插入操作十分灵活,你既可以通过给表里面所有的字段赋值,完整的插入一条数据记录,也可以在插入记录的时候,只给部分字段赋值。

还是上面的demo.goodsmaster表,其中包括了itemnumber, barcode, goodsname, specification, unit 和 price共6个字段。

我想要插入一条数据记录,其中包括了所有字段的值,就可以这样操作:

sql 复制代码
insert into demo.goodsmaster
(itemnumber, barcode, goodsname, specification, unit, price)
values (4, '0003', '尺子', '三角形', '把', 5);

运行这条SQL,然后对数据表进行查询:

sql 复制代码
mysql> select *
    -> from demo.goodsmaster;
+------------+---------+-----------+---------------+------+-------+
| itemnumber | barcode | goodsname | specification | unit | price |
+------------+---------+-----------+---------------+------+-------+
|          4 | 0003    | 尺子      | 三角型        | 把   |  5.00 |
+------------+---------+-----------+---------------+------+-------+
1 row in set (0.01 sec)

那如果我想插入一条记录,但是只给部分字段赋值,可以不?

比如说,客户有个商品,需要马上上线销售,目前只知道条码、名称和价格,其他的信息暂不录入,等之后再补,可以实现吗?

我们来尝试只给3个字段赋值,看看实际操作可以吗?

sql 复制代码
insert into demo.goodsmaster
(
-- 这里只给3个字段赋值,itemnumber、specification、unit不赋值
  barcode,
  goodsname,
  price
)
VALUES
(
  '0004',
  '测试',
  10
);

运行这条SQL语句,我们来查询表的数据,就会发现是可以的。

sql 复制代码
mysql> select *
    -> from demo.goodsmaster;
+------------+---------+-----------+---------------+------+-------+
| itemnumber | barcode | goodsname | specification | unit | price |
+------------+---------+-----------+---------------+------+-------+
|          4 | 0003    | 尺子      | 三角型        | 把   |  5.00 |
|          5 | 0004    | 测试      | NULL          | NULL | 10.00 |
+------------+---------+-----------+---------------+------+-------+
2 rows in set (0.00 sec)

我们之所以能够在插入一条数据记录的时候,只给部分字段赋值,原因在于我们对字段的定义方式。

那字段是怎么定义的呢,我们来查看一下表的结构,看看各个字段的定义:

sql 复制代码
mysql> desc demo.goodsmaster;
+---------------+---------------+------+-----+---------+----------------+
| Field         | Type          | Null | Key | Default | Extra          |
+---------------+---------------+------+-----+---------+----------------+
| itemnumber    | int           | NO   | PRI | NULL    | auto_increment |
| barcode       | text          | NO   |     | NULL    |                |
| goodsname     | text          | NO   |     | NULL    |                |
| specification | text          | YES  |     | NULL    |                |
| unit          | text          | YES  |     | NULL    |                |
| price         | decimal(10,2) | NO   |     | NULL    |                |
+---------------+---------------+------+-----+---------+----------------+
6 rows in set (0.01 sec)

可以看到,我们刚刚在插入数据的时候没有明确赋值的3个字段,都有着各自的特点。

specification和unit都可以是空值,而itemnumber则定义了自增约束。

我们在插入一条数据记录的时候,必须要考虑字段约束的3种情况。

  • 如果字段允许为空,而我们没有给它赋值,那么MySQL会自动给它赋与空值。在刚刚的代码中,specification和unit字段都允许为空,因此,如果数据插入语句没有指定这几个字段的值,MySQL会自动插入空值;
  • 如果字段是主键,就不能为空,这个时候,MySQL会按照我们添加的约束进行处理。比如字段itemnumber 是主键,不能为空,而我们定义了自增约束,所以MySQL自动在之前的最大值基础上增加1;
  • 如果有一个字段定义不能为空,又不是主键,当你插入一条数据记录的时候,就必须给这个记录赋值。

如果我们违反了字段的约束限制,会出现什么情况呢?

比如说,我们尝试把表demo.goodsmaster的字段specification改为不能为空:

sql 复制代码
alter table demo.goodsmaster
modify specification text not null;

运行这个 SQL 语句,系统会提示错误,原因就是我们刚才部分插入了一条数据记录,没有给字段"specification"赋值,这跟我们给字段"specification"添加非空约束的操作冲突了。

因此我们需要删除表中spcification值为空的数据记录,然后再修改字段约束:

sql 复制代码
delete from demo.goodsmaster
where itemnumber=5;

删除数据记录之后,在运行上面的语句,给字段specification添加非空约束,就成功了。

现在我们来验证一下非空约束。我们尝试部分插入一条数据记录,不给字段specification赋值:

sql 复制代码
insert into demo.goodsmaster
(barcode, goodsname, price)
values ('0004', '测试', 10);

运行这个SQL语句,MySQL会报错,提示字段specification没有默认值。也就是说,这个字段不能为空,如果插入数据时不给它赋值,就必须给它一个默认值。

现在我们清楚了,部分插入一条数据记录是可以的,但前提是,没有赋值的字段,一定要让MySQL知道如何处理,比如可以为空、有默认值,或者是自增约束字段,等等,否则,MySQL会提示错误。

在实际工作中呢,一次只插入一条数据,有时候会不够用。

所以接下来我们来讲解MySQL中的另外一种数据插入操作:把查询结果插入到数据表中。

插入查询结果

MySQL支持把查询的结果插入到数据表中,我们可以指定字段,甚至是数值,插入到数据表中。语法结构如下:

sql 复制代码
insert into 表名 (字段名)
select 字段名或值
from 表名
where 条件

好了,添加数据的操作就讲完了,现在我们知道了,我们给一张数据表插入一条数据记录的时候,可以给所有的字段赋值,也可以给部分字段赋值,这取决于字段的定义。

如果字段不能为空并且没有默认值,就必须赋值。另外,我们还可以通过把一个查询结果插入数据表中的方式,提高添加数据的效率。

删除数据

数据删除的语法很简答,如下:

sql 复制代码
delete from 表名
where 条件

如果我们现在想把刚才用过的表 demo.goodsmaster 里的内容清理一下,删除全部数据,可以通过下面的 SQL 语句来实现:

sql 复制代码
delete from demo.goodsmaster;

这里给出一个建议是:我们要习惯删除数据的时候,添加条件语句where,防止误操作。

假如我们的数据表 demo.goodsmaster 中有如下数据记录:

sql 复制代码
mysql> select *
    -> from demo.goodsmaster;
+------------+---------+-----------+---------------+------+-------+
| itemnumber | barcode | goodsname | specification | unit | price |
+------------+---------+-----------+---------------+------+-------+
|          4 | 0003    | 尺子      | 三角型        | 把   |  5.00 |
|          5 | 0004    | 测试      | NULL          | NULL | 10.00 |
+------------+---------+-----------+---------------+------+-------+
2 rows in set (0.00 sec)

如果我们要删除表中所有数据,可以这样写:

sql 复制代码
delete from demo.goodsmaster where itemnumber > 1;

修改数据

MySQL修改数据的语法:

sql 复制代码
update 表名
set 字段名=值
where 条件

注意:不要修改主键字段的值,因为主键是数据记录的唯一标识,如果修改了主键的值,就有可能会破坏数据的完整性。

查询数据

select|where|group by|having

我们来看看查询语句的语法结构:

sql 复制代码
select *|字段列表
from 数据源
where 条件
group by 字段
having 条件
order by 字段
limit 起始点,行数

在这些字段中,select、where、group by和having 比较好理解,我们只需要知道它们的含义就行了:

  • select:查询关键字,表示我们要做一个查询。" * "是一个通配符,表示我们要查询表中的所有字段。当然了,我们也可以将表中要查询的字段罗列出来,这样的话,查询的结果中可以只显示你想要查询的字段内容。
  • where:表示查询条件。我们可以把要查询的数据所满足的条件,放在where关键字之后。
  • group by:作用是告诉MySQL,查询结果要如何分组,经常与MySQL的聚合函数一起使用。
  • having:用于筛选查询结果,跟where类似。

from、order by和 limit相对来说比较复杂,需要注意的地方比较多,请接着看:

from

from关键字标识查询的数据源。我们现在只学习了单个数据库,后面我们在学习关联表的时候,from关键字的后面会跟上更加复杂的数据表联接。

有一点需要注意的是,数据源不一定是表哦,也可以是一个查询的结果。比如:

红色框里的部分叫做派生表(derived table),或者子查询(subquery),意思是我们把一个查询结果数据集当做一个虚拟的数据表来看待。

MySQL中规定,必须要用AS关键字给这个派生表起一个别名。也就是上图的'a'.

order by

ORDER BY 的作用,是告诉 MySQL,查询结果如何排序。ASC 表示升序,DESC 表示降序。

举个简单的小例子,带你看看 ORDER BY 是怎么使用的(这里我们仍然假设字段"specification"和"unit"允许为空)。我们向表 demo.goodsmaster 中插入 2 条数据:

sql 复制代码
insert into demo.goodsmaster
(
  barcode,
  goodsname,
  price
)
values
(
  '0003',
  '尺子1',
  15
);
insert into demo.goodsmaster
(
  barcode,
  goodsname,
  price
)
values
(
  '0004',
  '测试1',
  20
);

如果我们不控制查询结果的顺序,就会得到这样的结果:

sql 复制代码
mysql> select *
    -> from demo.goodsmaster;
+------------+---------+-----------+---------------+------+-------+
| itemnumber | barcode | goodsname | specification | unit | price |
+------------+---------+-----------+---------------+------+-------+
|          4 | 0003    | 尺子      | 三角型        | 把   |  5.00 |
|          5 | 0004    | 测试      | NULL          | NULL | 10.00 |
|          6 | 0003    | 尺子1     | NULL          | NULL | 15.00 |
|          7 | 0004    | 测试1     | NULL          | NULL | 20.00 |
+------------+---------+-----------+---------------+------+-------+
4 rows in set (0.00 sec)

如果我们使用 ORDER BY 对查询结果进行控制,结果就不一样了:

sql 复制代码
mysql> select *
    -> from demo.goodsmaster
    -> order by barcode asc, price desc;
+------------+---------+-----------+---------------+------+-------+
| itemnumber | barcode | goodsname | specification | unit | price |
+------------+---------+-----------+---------------+------+-------+
|          6 | 0003    | 尺子1     | NULL          | NULL | 15.00 |
|          4 | 0003    | 尺子      | 三角型        | 把   |  5.00 |
|          7 | 0004    | 测试1     | NULL          | NULL | 20.00 |
|          5 | 0004    | 测试      | NULL          | NULL | 10.00 |
+------------+---------+-----------+---------------+------+-------+
4 rows in set (0.00 sec)

可以看到,查询结果会先按照字段 barcode 的升序排序,相同 barcode 里面的字段,按照 price 的降序排序。

limit

LIMIT 的作用是告诉 MySQL 只显示部分查询的结果。比如,现在我们的数据表 demo.goodsmaster 中有 4 条数据,我们只想要显示第 2、3 条数据,就可以用 LIMIT 关键字来实现:

sql 复制代码
mysql> select *
    -> from demo.goodsmaster
    -> limit 1,2;
+------------+---------+-----------+---------------+------+-------+
| itemnumber | barcode | goodsname | specification | unit | price |
+------------+---------+-----------+---------------+------+-------+
|          5 | 0004    | 测试      | NULL          | NULL | 10.00 |
|          6 | 0003    | 尺子1     | NULL          | NULL | 15.00 |
+------------+---------+-----------+---------------+------+-------+
2 rows in set (0.00 sec)

这里的"LIMIT 1,2"中,"1"表示起始位置,MySQL 中,起始位置的起点是 0,1 表示从第 2 条记录开始;"2"表示 2 条数据。因此,"LIMIT 1,2"就表示从第 2 条数据开始,显示 2 条数据,也就是显示了第 2、3 条数据。

最后再补充一点,如果我们把查询的结果插入到表中时,导致主键约束或者唯一性约束被破坏了,就可以用"on duplicate"关键字进行处理。这个关键字的作用是,告诉 MySQL,如果遇到重复的数据,该如何处理。

举个例子: 假设用户有 2 个各自独立的门店,分别有自己的系统。现在需要引入连锁经营的模式,把 2 个店用一套系统统一管理。那么首先遇到的问题就是,需要进行数据整合。下面我们就以商品信息表为例,来说明如何通过使用"on duplicate"关键字,把两个门店的商品信息数据整合到一起。

假设门店 A 的商品信息表是"demo.goodsmaster",代码如下:

sql 复制代码
mysql> select *
    -> from demo.goodsmaster;
+------------+---------+-----------+---------------+------+------------+
| itemnumber | barcode | goodsname | specification | unit | salesprice |
+------------+---------+-----------+---------------+------+------------+
|          1 | 0001    | 书        | 16开          | 本   |      89.00 |
|          2 | 0002    | 笔        | 10支装        | 包   |       5.00 |
|          3 | 0003    | 橡皮      | NULL          | 个   |       3.00 |
+------------+---------+-----------+---------------+------+------------+
3 rows in set (0.00 sec)

门店 B 的商品信息表是"demo.goodsmaster1":

sql 复制代码
mysql> select *
    -> from demo.goodsmaster1;
+------------+---------+-----------+---------------+------+------------+
| itemnumber | barcode | goodsname | specification | unit | salesprice |
+------------+---------+-----------+---------------+------+------------+
|          1 | 0001    | 教科书    | NULL          | NULL |      89.00 |
|          4 | 0004    | 馒头      |               |      |       1.50 |
+------------+---------+-----------+---------------+------+------------+
2 rows in set (0.00 sec)

假设我们要把门店 B 的商品数据,插入到门店 A 的商品表中去,如果有重复的商品编号,就用门店 B 的条码,替换门店 A 的条码,用门店 B 的商品名称,替换门店 A 的商品名称;如果没有重复的编号,就直接把门店 B 的商品数据插入到门店 A 的商品表中。这个操作,就可以用下面的 SQL 语句实现:

sql 复制代码
insert into demo.goodsmaster
select * from demo.goodsmaster as a
on duplicate key update barcode = a.barcode, goodsname = a.goodsname;

运行结果如下:

sql 复制代码
-- 运行结果如下
mysql> select *
    -> from demo.goodsmaster;
+------------+---------+-----------+---------------+------+------------+
| itemnumber | barcode | goodsname | specification | unit | salesprice |
+------------+---------+-----------+---------------+------+------------+
|          1 | 0001    | 教科书    | 16开          | 本   |      89.00 |
|          2 | 0002    | 笔        | 10支装        | 包   |       5.00 |
|          3 | 0003    | 橡皮      | NULL          | 个   |       3.00 |
|          4 | 0004    | 馒头      |               |      |       1.50 |
+------------+---------+-----------+---------------+------+------------+
4 rows in set (0.00 sec)
相关推荐
清酒伴风(面试准备中......)15 分钟前
小白学编程之——数据库如何性能优化
数据库·oracle·性能优化
默心24 分钟前
centos7部署mysql5.7
linux·运维·mysql·centos
The Future is mine42 分钟前
SQL Server中delete table和truncate table删除全表数据哪个快?
数据库
IT成长史43 分钟前
deepseek梳理java高级开发工程师springboot面试题2
java·spring boot·后端
是麟渊43 分钟前
【大模型面试每日一题】Day 17:解释MoE(Mixture of Experts)架构如何实现模型稀疏性,并分析其训练难点
人工智能·自然语言处理·面试·职场和发展·架构
瀚高PG实验室1 小时前
HGDB插入超长字段报错指示列名的问题处理
数据库
好吃的肘子1 小时前
MongoDB 高可用复制集架构
数据库·mongodb·架构
qq_266348731 小时前
springboot AOP中,通过解析SpEL 表达式动态获取参数值
java·spring boot·后端
bing_1582 小时前
MQTT 在Spring Boot 中的使用
java·spring boot·后端·mqtt
兮兮能吃能睡2 小时前
Python之with语句
数据库·python