目录
- 1 前言(CRUD)
- 2 新增(Create)
- 2.1 全列插入
- 2.2 指定列插入
- 2.3 关于日期和时间的插入
- 3 查询(Retrieve)
- 3.1 全列查询
- 3.2 指定列查询
- 3.3 查询字段为表达式
- 3.4 取别名
- 3.5 去重
- 3.6 排序
- 3.7 条件查询
- 3.8 分页查询
- 4 更新(Update)
- 5 删除(Delete)
1 前言(CRUD)
CRUD : 即增加(Create)、查询(Retrieve)、更新(Update)、删除(Delete)四个单词的首字母缩写。
在了解数据库表的增删改查之前,我们需要先进行一些准备工作,即在选中的数据库中准备两张表:
-- 创建一张学生表
DROP TABLE IF EXISTS student;
CREATE TABLE student (id INT,sn INT comment '学号',name VARCHAR(20) comment '姓名',qq_mail VARCHAR(20) comment 'QQ邮箱'
);-- 创建考试成绩表
DROP TABLE IF EXISTS exam_result;
CREATE TABLE exam_result (id INT,name VARCHAR(20),chinese DECIMAL(3,1),math DECIMAL(3,1),english DECIMAL(3,1)
);
对于类来说:每一行就是一个学生,每一列就是一个学生的某个属性。
class student{private int id;private int sn;private String name;private String qq_mail;
}
等后面了解到MyBatis等框架的时候就可以用到了。
2 新增(Create)
2.1 全列插入
插入两条记录,VALUES后面括号里的数量必须和定义表的列的数量及顺序一致。例如:
INSERT INTO student VALUES (100, 10000, '唐三藏', NULL);
INSERT INTO student VALUES (101, 10001, '孙悟空', '11111');
2.2 指定列插入
插入两条记录,VALUES后面括号里的数量必须和指定列数量及顺序一致。例如:
INSERT INTO student (id, sn, name) VALUES (102, 20001, '曹孟德'),(103, 20002, '孙仲谋');
如果没有指定某个字段的值,那么默认是NULL,但是注意,后期会了解到约束。
2.3 关于日期和时间的插入
假如我们想对timestamp这个数据类型进行插入操作,则插入的格式必须写为
'2024-01-25'
或2024-01-25 18:55:42
。
3 查询(Retrieve)
我们需要先在前面创建的exam_result表中插入一些数据,具体插入操作如下所示:
INSERT INTO exam_result (id,name, chinese, math, english) VALUES(1,'唐三藏', 67, 98, 56),(2,'孙悟空', 87.5, 78, 77),(3,'猪悟能', 88, 98, 90),(4,'曹孟德', 82, 84, 67),(5,'刘玄德', 55.5, 85, 45),(6,'孙权', 70, 73, 78.5),(7,'宋公明', 75, 65, 30);
3.1 全列查询
SELECT * FROM 表名;
*
代表当前表当中的所有字段。通常情况下不建议使用*
进行全列查询。因为:
- 查询的列越多,意味着需要传输的数据量越大;
- 可能会影响到索引的使用。(索引待后面进行了解)
3.2 指定列查询
指定列的顺序不需要按定义表的顺序来。例如:
SELECT id, name, english FROM exam_result;
3.3 查询字段为表达式
- 表达式不包含字段。例如:
SELECT id, name, 10 FROM exam_result;
注:此时第三列列名、内容统一都为10。 - 表达式包含一个字段。例如:
SELECT id, name, english + 10 FROM exam_result;
注:此时第三列列名为 english + 10,列的内容为各学生的英语成绩加10。 - 表达式包含多个字段。例如:
SELECT id, name, chinese + math + english FROM exam_result;
注:此时第三列则代表了查询总成绩,列名为chinese + math + english,列的内容为各学生的三门总成绩和。
3.4 取别名
取别名的作用: 就是当列名或者表名太复杂了,比如太长了,其此时就可以用别名代替!例如:
- 给上面总成绩的示例的第三列取一个统一的列名为总分。意思是取之前第三列的名字为 chinese + math + english,取别名后第三列的名字为:总分。
SELECT id, name, chinese + math + english as 总分 FROM exam_result;
- 或者给表取个别名。
SELECT id, name, chinese + math + english as 总分 FROM exam_result as exam;
当然 as 也可以省略!即上面两个示例可以修改为:
SELECT id, name, chinese + math + english 总分 FROM exam_result;
SELECT id, name, chinese + math + english 总分 FROM exam_result exam;
3.5 去重
使用 DISTINCT 关键字对某列数据进行去重。例如:
- 针对我们前面在exam_result表中插入的数据,可以发现math数学成绩那一列有两个98,我们可以先进行数学成绩那一列的查询,再进行一下去重操作。
SELECT math FROM exam_result;
SELECT DISTINCT math FROM exam_result;
- 但是疑问
SELECT id,name, DISTINCT math FROM exam_result;
这样的SQL语句是否可以去重?运行之后你会发现,不可以!
原因:以上这条语句位置不对!需要把去重放在第一位!! - 但是你会发现将示例2中的语句修改为
SELECT DISTINCT math,id,name FROM exam_result;
这样以后,运行结果并没有把两个数学成绩为98去掉一个,而是都选择了保留。那么为什么会发生这种现象呢?去重的原理又到底是什么?
因此,我们需要记住:去重针对的是所有的字段!只有当SELECT DISTINCT math,id,name FROM exam_result;
中的三个字段同时重复的时候,才会去重!
3.6 排序
- 将查询结果根据数学成绩进行从低到高(升序)的排序:
select * from exam_result order by math;
或select * from exam_result order by math asc;
。
因此我们可以知道order by 默认情况下为升序(从小到大)。 - 将查询结果根据数学成绩进行从高到低(降序)的排序:
select * from exam_result order by math desc;
。
我们会发现desc这个词见了2次了,一次是前面显示表结构的时候desc 表名;
,另一次就是现在表降序。
desc实际上是一个关键字,但要注意关键字不要瞎用。假设你要创建一个表,这个表表名叫做desc,按照正常所学应该是先drop table if exists desc;
,然后再create table desc(id int,name varchar(10));
。但是你运行之后发现会报错,不能运行通过。
因此,你的变量名要是为MySQL当中的关键字,需要这样写才能运行通过:
drop table if exists `desc`;
create table `desc`(id int,name varchar(10)
);
- 使用表达式及别名排序:
查询同学及总分,由高到低排序:SELECT name, chinese + english + math FROM exam_result ORDER BY chinese + english + math DESC;
;
然后我们把chinese + english + math这一列起个别名为total进行排序:SELECT name, chinese + english + math total FROM exam_result ORDER BY chinese + english + math DESC;
,运行之后我们发现是可以的,成功了!
但此时我们想着要是SELECT name, total FROM exam_result ORDER BY chinese + english + math total DESC;
这样写能成功吗?这时我们发现不可以!错误原因:查询的顺序问题,它会首先执行SELECT name, total FROM exam_result;
,但是此时并不认识total是啥,因此会报错。
因此我们修改为SELECT name, chinese + english + math total FROM exam_result ORDER BY total DESC;
则也是可以成功的! - 可以对多个字段进行排序,排序优先级随书写顺序:
查询同学各门成绩,依次按 数学降序,英语升序,语文升序的方式显示:
SELECT name, math, english, chinese FROM exam_result ORDER BY math DESC, english, chinese;
总结:
- order by asc 和 order by 默认是从低到高进行排序的。
- order by desc是从高到低进行排序的。
- 对于MySQL的关键字在用作变量名的时候一定要加符号:``。
- NULL 数据排序,视为比任何值都小,升序出现在最上面,降序出现在最下面。
- 没有 ORDER BY 子句的查询,返回的顺序是未定义的,永远不要依赖这个顺序。
3.7 条件查询
- 查询英语不及格的同学及英语成绩 ( < 60 ):
SELECT name, english FROM exam_result WHERE english < 60;
。 - 查询英语不及格的同学及英语成绩 ( < 60 ),并按升序进行排序:
SELECT name, english FROM exam_result WHERE english < 60 order by english;
。
但要注意:SELECT name, english FROM exam_result order by english WHERE english < 60;
这样写是不可以的,会报错! - 查询数学成绩是 58 或者 59 或者 98 或者 99 分的同学及数学成绩:
SELECT name, math FROM exam_result WHERE math IN (58, 59, 98, 99);
或
SELECT name, math FROM exam_result WHERE math = 58 OR math = 59 OR math = 98 OR math = 99;
。 - 查询数学成绩不是 58 或者 59 或者 98 或者 99 分的同学及数学成绩:
SELECT name, math FROM exam_result WHERE math not IN (58, 59, 98, 99);
。 - 模糊查询:
(1) 匹配任意多个(包括 0 个)字符,例如:
SELECT name FROM exam_result WHERE name LIKE '孙%';
这条SQL语句所匹配的数据一定是以 孙 这个字开始的,将匹配到孙悟空、孙权。
SELECT name FROM exam_result WHERE name LIKE '%孙%';
这条SQL语句将匹配的数据一定是以 孙 这个字在中间的。
SELECT name FROM exam_result WHERE name LIKE '%孙';
这条SQL语句所匹配的数据一定是以 孙 这个字结尾的。
(2)匹配严格的一个任意字符,例如:
SELECT name FROM exam_result WHERE name LIKE '孙_';
这条SQL语句所匹配的数据一定是以 孙 这个字开始的,且记住一个下划线仅对应一个模糊匹配的字,将匹配到孙权。
SELECT name FROM exam_result WHERE name LIKE '孙__';
这条SQL语句所匹配的数据一定是以 孙 这个字开始的,且记住一个下划线仅对应一个模糊匹配的字。所以这条语句将只会找到以孙开头且有3个字的,后两个字是模糊匹配的,将匹配到孙悟空。
比较运算符:
运算符 | 说明 |
---|---|
>, >=, <, <= | 大于,大于等于,小于,小于等于 |
= | 等于,NULL 不安全,例如 NULL = NULL 的结果是 NULL |
<=> | 等于,NULL 安全,例如 NULL <=> NULL 的结果是含有NULL的,数据NULL不会被忽略 |
!=、<> | 不等于,NULL 不安全,例如 NULL = NULL 的结果是 NULL |
BETWEEN a0 AND a1 | 范围匹配,[a0, a1],如果 a0 <= value <= a1,返回数据 |
IN(option,…) | 如果是 option 中的任意一个,返回数据 |
IS NULL | 是 NULL |
IS NOT NULL | 不是 NULL |
LIKE | 模糊匹配,% 表示任意多个(包括 0 个)任意字符;_ 表示任意一个字符 |
逻辑运算符:
运算符 | 说明 |
---|---|
AND | 多个条件必须都为 TRUE(1),结果才是 TRUE(1) |
OR | 任意一个条件为 TRUE(1), 结果为 TRUE(1) |
NOT | 条件为 TRUE(1),结果为 FALSE(0)} |
注:
- WHERE条件可以使用表达式,但不能使用别名。
- AND的优先级高于OR,在同时使用时,需要使用小括号()包裹优先执行的部分。
3.8 分页查询
提问: 为何要分页?
答:主要是有的时候,数据量太大了,那么一次性查找数据的时候,系统会执行SQL语句,此时查询是需要时间的,有可能系统就会被卡住。所以,一般优化的方案就是用分页查询。
原理: 每次只查询,当前页需要显示的数据即可。也就是说,如果每页10条数据,那么只查询10条数据。每次点击下一页的时候,又会请求查询10条数据,这样效率就提高了!!!
语法:
-- 起始下标为 0
-- 从 0 开始,筛选 n 条结果
SELECT ... FROM table_name [WHERE ...] [ORDER BY ...] LIMIT n;
-- 从 s 开始,筛选 n 条结果
SELECT ... FROM table_name [WHERE ...] [ORDER BY ...] LIMIT s, n;
-- 从 s 开始,筛选 n 条结果,比第二种用法更明确,建议使用
SELECT ... FROM table_name [WHERE ...] [ORDER BY ...] LIMIT n OFFSET s;
注:
- 如果n的值过大,那么也没关系,只会查询到能查询的内容。
- 如果s的值过大,那么SQL不会报错,但是什么也查不到。
示例: 按 id 进行分页,每页 3 条记录,分别显示 第 1、2、3 页。
-- 第 1 页
SELECT id, name, math, english, chinese FROM exam_result ORDER BY id LIMIT 3 OFFSET 0;
-- 第 2 页
SELECT id, name, math, english, chinese FROM exam_result ORDER BY id LIMIT 3 OFFSET 3;
-- 第 3 页,如果结果不足 3 个,不会有影响
SELECT id, name, math, english, chinese FROM exam_result ORDER BY id LIMIT 3 OFFSET 6;
4 更新(Update)
语法: UPDATE table_name SET 更新内容 [WHERE ...] [ORDER BY ...] [LIMIT ...]
示例:
- 将孙悟空同学的数学成绩变更为 80 分:
UPDATE exam_result SET math = 80 WHERE name = '孙悟空';
- 将曹孟德同学的数学成绩变更为 60 分,语文成绩变更为 70 分:
UPDATE exam_result SET math = 60, chinese = 70 WHERE name = '曹孟德';
- 将总成绩倒数前三的 3 位同学的数学成绩加上 30 分:
UPDATE exam_result SET math = math + 30 ORDER BY chinese + math + english LIMIT 3;
但要注意:mysql的update语句,只支持更新前多少行,不支持从某行到某行!
例如:将总成绩倒数第二到第五的 3 位同学的数学成绩加上 30 分:
UPDATE exam_result SET math = math + 30 ORDER BY chinese + math + english LIMIT 1,3;
这样写是不可以的,会报错。就是因为mysql的update语句,只支持更新前多少行,不支持从某行到某行! - 将所有同学的语文成绩更新为原来的 2 倍:
UPDATE exam_result SET chinese = chinese * 2;
5 删除(Delete)
delete from 表 where 条件
示例如下:
- 删除孙悟空同学的考试成绩。
DELETE FROM exam_result WHERE name = '孙悟空';
- 删除整表数据。
DELETE FROM exam_result;
注意:直接删除整表数据会删除表内的所有数据,但是这张表还是存在的,只不过里面没有数据了!!!