表的增删查改
CURD是一个数据库技术中的缩写词,一般的项目开发的各种参数的基本功能都是CURD。作用是用于处理数据的基本原子操作。
CURD:
- Create(创建)、
- Retrieve(读取)、
- Update(更新)、
- Delete(删除)
1. Create插入数据(Insert细节操作)
INSERT [INTO] table_name [(column [, column] ...)] VALUES (value_list) [, (value_list)] ...
直接通过实例来学习:
先创建一个学生表(后续在学生表上进行操作)
1.1 单行数据插入:
- 主要需要理解的结构:
(需要插入的属性列) values(对应的值)
insert into students (插入中:into可省略,students就是要插入的表名) - 当values右边列属性不写,就是一次性插入所有属性(全列插入)
1.2 多行插入:
也很简单直接在插入的数据 用逗号分隔 连续插入(具体如下图)
同样能指定列插入,这里就不过诉了。
1.3 冲突时同步更新:
当插入数据时可能会有主键、唯一键冲突…等情况,假如直接插入会直接报错。
那么现在可以通过添加一些语法,让当有冲突(即已存在该数据)时,对冲突进行处理,让即使有问题也能插入,而不是直接报错。
语法:
on duplicate key update
例如:
下述插入许攸的情况,若直接插入,因为主机冲突的情况无法直接插入新的值。
那么我们使用(原SQL)on duplicate key update (更新SQL)这样就能插入,并且修改即使存在也会将他修改为新的
下面再看具体语法:
在插入语句后面添加:
INSERT ...... ON DUPLICATE KEY UPDATE
column = value [, column = value] ...
-- 0 row affected: 表中有冲突数据,但冲突数据的值和 update 的值相等
-- 1 row affected: 表中没有冲突数据,数据被插入
-- 2 row affected: 表中有冲突数据,并且数据已经被更新
select ROW_COUNT()-- 获取受影响函数
1.4 冲突时同步替换:
语法:
-- 主键 或者 唯一键 没有冲突,则直接插入;
-- 主键 或者 唯一键 如果冲突,则删除后再插入
replace into students (sn, name) VALUES (20001, '曹阿瞒');
Query OK, 2 rows affected (0.00 sec)
-- 1 row affected: 表中没有冲突数据,数据被插入
-- 2 row affected: 表中有冲突数据,删除后重新插入
实例:
当插入冲突时,会直接进行替换(此时就会显示2行影响行数),注意此处是删除后再插入(id会改变)
具体如下图:
2. Retireve读取数据(Select细节操作)
语法:
SELECT
[DISTINCT] {* | {column [, column] ...}
[FROM table_name]
[WHERE ...]
[ORDER BY column [ASC | DESC], ...]
LIMIT ...
同样是用实例来学习:
创建表并插入数据:
2.1 全列查询
通常情况下不建议使用 * 进行全列查询
1. 查询的列越多,意味着需要传输的数据量越大;
2. 可能会影响到索引的使用。(索引待后面课程讲解)
语法:
SELECT * FROM exam_result;
之前讲写了就不过诉了!
2.2 指定列查询
-- 指定列的顺序不需要按定义表的顺序来
和插入时类似在前面加上要查询的列名称,不同的是此时变成了FROM
SELECT id, name, english FROM exam_result;
2.3 查询字段为表达式
在select 后可以添加表达式,将会在查询结果中带上表达式结果。
表达式不包含字段时:
SELECT id, name, 10 FROM exam_result;
发现将会直接打印10(其实代表的是该表达式的计算结果)
查询有字段的表达式时:
并且还能通过as进行重命名:
如求一行中的成绩总和
其中as可以省略:
2.4 结果去重 DISTINCT
SELECT DISTINCT math FROM exam_result
很简单就是将查询到的重复数据只见一行。
2.5 where条件
比较运算符:
运算符 | 说明 |
---|---|
> , >=, <, <= | 大于,大于等于,小于,小于等于 |
= | 等于,只能用于数值的比较,NULL 不安全(不能比较),例如 NULL = NULL 的结果是 NULL |
<=> | 等于,NULL 安全,例如 NULL <=> NULL 的结果是 TRUE(1) |
!=, <> | 不等于NULL 不安全 |
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 个)任意字符;_ 表示任意一个字符 |
附:
=号,不能用于比较NULL值,比较NULL值需要使用<=>
具体如下:
当直接用 = 进行比较时比较后会为NULL、的使用<=>这样就能正常比较
逻辑运算符:
运算符 | 说明 |
---|---|
AND | 多个条件必须都为 TRUE(1),结果才是 TRUE(1) |
OR | 任意一个条件为 TRUE(1), 结果为 TRUE(1) |
NOT | 条件为 TRUE(1),结果为 FALSE(0 |
实例:
比较运算符
- 找英语成绩不合格的人:
between运算符的使用
- 语文成绩在 80 ~ 90 分的同学和成绩
上述和使用between a1 and a2 (a1 ~ a2)一样,但between更方便。
in运算符的使用
in:如果是 option 中的任意一个,返回 TRUE(1)
- 取出数学成绩 58 或 59 或 98或99 的同学和成绩
可以直接使用 or
也可以使用 math in(58,59,…)
like模糊查询
使用 like:
%
表示模糊查询后面任意多个(包括 0 个)任意字符;_
表示模糊查询后面任意一个字符
- 查询孙某某(使用%,因为不确定其后面有几个字)
若写成_(就只能查孙某):
where后面能使用表达式(和字段)
- 语文好于英语成绩
- 总分在200以下的同学
注意其中不能在where后面使用as重命名的变量,这是因为在select中是where是先执行的,然后才到筛选列,所以也就是as还未定义,无法使用。
具体执行顺序:- from(先找表)
- where(筛选条件),
- select(查找的列属性)
所以因为先where,才到列属性,所以重命名是不能使用的(列属性处还未被定义,就不能在where中使用了)
not运算符
-
寻找语文成绩大于80且不姓孙
-
是孙某同学,否则要求总成绩 > 200 并且 语文成绩 < 数学成绩 并且 英语成绩 > 80
- 要么是孙某
- 否则:要求总成绩 > 200 and 语文 < 数学 and 英语 > 80
- 可先把后面一长串的内容先写 然后 再去加上前面的孙某
NULL的查询
重新新建一个表test:
- 查询NULL
- 查询不为空
- NULL不参与比较运算,要比较只能使用<=> 、<>
2.6 order by语句(结果排序)
- ASC 为升序(Ascending)(从小到大)
- DESC 为降序(Descending)(从大到小)
- 默认为 ASC
- 没有order by子句的查询,返回的顺序是未定义的,永远不要依赖这个顺序
语法:
SELECT ... FROM table_name [WHERE ...]
ORDER BY column [ASC|DESC], [...];
实操:
ASC升序:
- 按数学成绩升序显示
- 降序desc
NULL值在排序中,默认设置为比任何值都要小
多字段排序,排序优先级随书写顺序
具体理解如下:
查询同学各门成绩,依次按 数学降序,英语降序,语文升序的方式显示
上图中先按数学降序(数学写在英语前面),当数学相等时才按英语降序,最后才考虑写到最后的语文
建议就是向上图一样,将排序的 方式全部列全出来,不要去使用MySQL默认的情况(无法掌控)
order by默认升序
可以在order by 中使用前面的as别名
因为在order by中需要对数据进行排序,一定要先有适合的数据才排序(所以他是先执行前面的列属性筛选那么它就能排序)
2.7 limit的使用(筛选分页结果)
- 直接在select后面加上limit表示需要的行数(从开始到第n行)
- 当limit 还能从 指定位置开始,读取连续个数(pos,len)(并且注意:开始位置是从0开始的)
如下图:从第一个开始读,3个
- 在limit读取行数的前提下,还能通过offset设置开始的行数(同样是从0开始)
建议对未知表查询时,对limit限制为1,防止数据过大
limit的作用,类似于网页中常见的页面的1、2、3、4 。。。分页显示数据。
如下图:
limit的执行阶段会更加靠后,因为只有最后将所有数据都准备好了,才到最终的显示,而limit的本质功能也就是显示,所以将排到最后。
结合上面多个读取数据的方法实例:
获取班级第一(如下图):
SELECT name, (english + math + chinese) AS total
FROM exam_result
WHERE english + math + chinese > 200
ORDER BY total DESC
LIMIT 1;
3. 插入 查询结合使用
插入查询结果
原理:select支持直接将查询的结果插入
INSERT INTO table_name [(column [, column ...])] SELECT ...
实例删除表中的重复记录:
1. 创建表
CREATE TABLE duplicate_table (id int, name varchar(20));
2. 插入信息
INSERT INTO duplicate_table VALUES
(100, 'aaa'),
(100, 'aaa'),
(200, 'bbb'),
(200, 'bbb'),
(200, 'bbb'),
(300, 'ccc');
此时需要将重复值删除,那应该怎么操作呢
原理:将 select distinct(去重查询)和 insert 插入 结合
将原表的数据,去重后的数据 全部 插入一个新表(相同结构!)中(将原表命修改、创建新表替代该名)
具体如下sql语句:
- 创建一张空表 no_duplicate_table,结构和 duplicate_table 一样(使用LIKE创建)
CREATE TABLE no_duplicate_table LIKE duplicate_table;
2. 插入查询后去重的数据到新表中(插入结合查询使用)
INSERT INTO no_duplicate_table SELECT DISTINCT * FROM duplicate_table;
3. 进行重命名(rename),将源duplicate_table 改成 old_…。然后再把no_duplicate_table 改成 原表命
RENAME TABLE duplicate_table TO old_duplicate_table,
no_duplicate_table TO duplicate_table;
使用rename是因为:要等一切都就绪了统一放入(更新生效)
这里原理:主要是要保证在文件拷贝过程中的原子性问题(因为要保证,在上传该文件过程中没有同名的文件也上传),而拷贝过程中是难易保证原子(假设过程很久),所以若是使用修改名称,先将数据准备好的前提下(这里就以及完成上传步骤了),那么将很容易达成原子要求。