初识MySQL(二)

目录

一、MySQL表的增删查改的基础使用

1.1 新增(Create)

1.2 查询(Retrieve)

1. 21数据的查询分为以下几个部分

1.22 从一个数据表中进行查询

1.23 where 条件

1.24 select

1.25 对检索出来的记录进行排序 order by

1.26 分片 limit + offset 

1.3 更新(Update)

1.4 删除(Delete)


一、MySQL表的增删查改的基础使用

注释:在SQL中可以使用“--空格+描述来表示注释说明

CURD:即新增(Create)、查询(Retrieve)、更新(Update)、删除(Delete)

CREATE TABLE `books` (
  `bid` int(11) NOT NULL AUTO_INCREMENT COMMENT '书籍的主键',
  `name` varchar(45) NOT NULL COMMENT '书籍的名称,我们假设书籍不会重复',
  `total` int(11) NOT NULL DEFAULT '0' COMMENT '图书馆应该有多少本这书',
  `current` int(11) NOT NULL DEFAULT '0' COMMENT '现在图书馆有多少本这书',
  PRIMARY KEY (`bid`),
  UNIQUE KEY `name_UNIQUE` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='图书馆系统的书籍管理表';

1.1 新增(Create)

如果设置过默认库,则直接插入默认库的books表内

insert into books (name, total, current) values
	('三国演义', 10, 10),
	('红楼梦', 20, 20),
    ('西游记', 30, 30),
    ('水浒传', 40, 40);

由于name位置是UQ(unique),所以如果再次插入相同name的书籍,则会报错

-- 由于现在的默认库是 ccb_1211,所以 books 的隐含台词是 ccb_1211.books
insert into books (name) values ('红楼梦');

-- 在第一条语句执行成功的前提下,再次执行,会失败,因为破坏了 name 上的唯一约束
insert into books (name) values ('红楼梦');

-- 一次性插入多条记录
insert into books (name) values ('JavaSE'), ('JavaDS'), ('JavaDB');

AI只能保证是自增的,但是不保证是连续的,例如我们这里的主键bid勾上了自增AI,先插入的书红楼梦 bid = 1,第二次插入红楼梦由于name是唯一的,所以插入失败,但是bid = 2还是被消耗掉了,所以后面的书就从bid = 3开始插入。

bid  name
1	红楼梦
3	JavaSE
4	JavaDS
5	JavaDB

字段的顺序和建表时的顺序无关,只要和后边的 values 的顺序对应上即可

insert into books (total, name, current) values 
	(10, '春', 10), 
    (20, '夏', 20),
    (30, '秋', 30),
    (40, '冬', 40);

没有默认值的字段,没有设置值,会报错, name 没有默认值,且没有指定值

insert into books (current) values (100);

如何才能成功的进行插入

1.要求所有的字段必须都有值,字段有默认值的除外(设置默认值/自增/运行为Null)

2.要求插入的所有值满足类型要求

3.要求插入的所有字段的值必须满足字段约束:NN,UQ等

-- 全字段插入时
insert into books (bid, name, total, current) values (100, '一百', 100, 100);
-- 全字段插入时,可以使用自增
insert into books (bid, name, total, current) values (null, '一百1', 100, 100);
-- 全字段插入时,可以省略字段
insert into books values (null, '一百2', 100, 100);

1.2 查询(Retrieve)

1. 21数据的查询分为以下几个部分

select 。。。

from 数据源(表)

where 条件

order by 排序的依据

limit + offset  分片

1. 从哪里进行数据的检索     from...

2. 应该检索哪些记录出来     where...

3. 具体要展示记录的是什么投影  select...

4. 将记录按照指定顺序排序    order by...

5. 排序的结果中获取切片      limit + offset

1.22 从一个数据表中进行查询

from 的后面跟上表名(books),在没有 where 条件的情况下,所有的记录都视为满足条件,select * 代表表中有哪些字段,展示哪些字段

select * from books;
//这行代码就是把books表所有内容全部输出,满足条件的记录有多少,就有多少行(暂时先不考虑 limit)

from 后边的表可以起一个别名(alias),以后用b这个别名就可以代表books

select * from books as b;
-- as 可以省略
select * from books b;

1.23 where 条件

给定一个逻辑表达式
将表中所有记录代入到这个逻辑表达式中
只检索逻辑表达式的结果是 true 的,mysql 中的 0 视为 false,非 0 视为 true
= 代表相等判断,在 SQL 中,== 这个运算符不存在

select bid, name, total, current from books where bid = 2;
//找到bid = 2的字段,输出他的name,total,current

where 条件的运算符

>, >=,  <, =大于,大于等于,小于,小于等于
=等于,NULL不安全,例如NULL = NULL的结果是NULL
<=>等于,NULL安全。例如NULL = NULL的结果是TRUE(1)
!=, <>不等于
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个)任意字符;_ 表示任意一个字符
AND多个条件必须都为TRUE,结果才是TRUE
OR任意一个条件时TRUE,结果就是TRUE
NOT条件为TRUE,结果为FALSE

And 的优先级高于OR,先对and进行运算,再对OR进行运算

select * from books where 1 = 1;	-- 所有记录
select * from books where 1 = 2;	-- 一条记录都没有
select * from books where bid != 2 and total > 10;
select * from books where (bid != 2 and bid != 3) or total > 10;
select bid, name, total, current, bid != 2, bid != 3, bid != 2 and bid != 3, total > 10 from books;

表达式 c between start to end; c是否存在于【start,end】这个左闭右闭的区间内

所以,隐藏的含义就是C得是一个可以视为区间的类型,比如int,日期,时间        

select 1 between 0 and 5;
select '2022-12-12' between '2019-12-12' and '2025-12-12';
select '09:48:32' between '08:00:00' and '12:00:00';

把 between ... and ... 代入到 where 条件中

select * from books where total between 20 and 30;

IN(option,...)

因为表内只有三国演义和红楼梦,所以只会返回这两本书的所有字段

select * from books where name in ('三国演义', '哈利波特', '红楼梦');

关于NULL的理解

1. NULL(空)代表未知

2. 凡是有null参加的表达式,得到的结果仍然是null

select null;
select 1 + null;
select 1 * null;
select 1 - null;
select 1 / null;
select 1 = null;
select 1 != null;
select null = null;
select null != null;

3. 在布尔运算的时候,null视为是false

select id, name from test1 where name = null;	-- 这个查出来多少条记录	0
select id, name from test1 where name != null;	-- 这个查出来多少条记录	0

-- 针对 null 的比较,不能简单的使用 = 和 != 比较
-- 1) 标准做法,使用  col is null 或者 col is not null <=> not (col is null)
-- 2) 不是很常见的做法,使用 <=> 进行比较   not (a <=> null)
-- <=> 也可以进行非 null 的正常相等比较
select id, name, name is null, name is not null from test1;
select id, name, name <=> null, not name <=> null from test1;
select 1 <=> 1, null <=> null;
select 1 = 1, null = null;

关于字符串的模糊匹配

xxx like '...', %表示任意多个(包括0个)任意字符;_ 表示任意一个字符,且必须为1个字符

select '张' like '张%';  -- 返回true
select '张三' like '张%';  -- 返回true
select '张一二三四五六七八九十' like '张%';   -- 返回true
select '小张' like '张%';  -- 返回false

select '张' like '张_'; -- 返回false
select '张三' like '张_';  -- 返回true
select '张一二三四五六七八九十' like '张_';  -- 返回false
select '小张' like '张_';  -- 返回false

MySQL中like 查询效率不一定很高,所以不要滥用

如果非要用,尽量使用'张%' 或者'张_' 

尽量不要使用'%张' 或者'_张' 

原因和内部的存储结构有关,一般称这个原则为最左匹配原则

where条件小结:

逻辑上,将所有记录,带入到where后面的逻辑表达式中,得到表达式的boolean值结果,只留下结果为true的记录

1. 相等判断使用 =; <=>也代表相等判断,且多个null的判断

2. not, and, or 必须这么写,注意优先级

3. x betweens s and e; 在左闭右闭区间内检索

4. e in (e1,e2,... ), 元素在不在集合中

5. 关于null的理解以及比较,is null / <=>

6. 字符串的模糊匹配    %和_的使用

1.24 select

1. 直接写个 select * , 代表所有字段都展示,并且展示的顺序按照建表的顺序来

2. 实际应用中不建议使用*,直接给出字段名称,要几个就输入几个字段,字段之间用逗号分割

3. 可以起别名:select name n from books

4. 可以有函数运算

upper(...)  把字符串变成大写

concat(...) 连接几个字符串

substr(...)  切割子串

select 'hello', upper('hello');
select 'HELLO', lower('HELLO');
select concat('hello', 'world');
select concat('hello', ' ', 'world');
select concat('hello', ' ', 'world', '!');
-- 第一个字符是从 1 开始,不是从 0
select substr('hello', 1, 3); --返回hel

5. select distinct

由于distinct会合并相同的记录,所以会影响检索出来的行数

例如现在表内有4个total值: 10, 20,10,20

如果select total 则输出10, 20,10,20

但如果是select distinct total则只会输出独特的项 10,20

//这两种写法都可以
select distinct total from books;
select distinct(total) from books;

select 小结

1. 除了几个特殊情况外,投影的规则,不影响最终检索出来的行数

2. 投影中出现了*,就不能出现其他东西了

3. 除了*之外,都可以起别名

4. distinct 做去重,不能是*;有了distinct之后,就不能出现其他字段了

select name, total from books;
//下面的就会报错,name是正常输出所有字段,但是distinct会做去重来影响字段
select name, distinct(total) from books;

1.25 对检索出来的记录进行排序 order by

1. 如果没有指定排序规则,则应该认为检索出来的顺序是未定义行为(无序的)

2. order by 其中order是排序的意思,by是以什么依据来进行排序

-- 使用 order by
select * from books;	-- 无序
select * from books order by bid;	-- 以 bid 作为顺序排序,按照默认规则(升序)
select * from books order by bid asc;	-- 升序
select * from books order by bid desc;	-- 降序

如果有相同的,则相同的记录之间的顺序仍是未定义顺序,如果有多个total值相等,则total向等的值的顺序是未定义的

select * from books order by total asc;

如果想要让total相等的字段变得有序,需要引入第二次排序规则

先按照 total 的升序进行排序
针对 total 相等的记录之间,按照 current 的倒序排序
多次排序之间的升降序可以不同

select * from books order by total asc, current desc;

order by 也可以用于表达式

select bid, name, total, current, total - current from books order by total - current asc;
select bid, name, total, current, total - current from books order by total - current desc;

1.26 分片 limit + offset 

1. 分片必须是在已经有序的结果上才有确定的结果

2. 传入两个东西:从哪开始取 offset (从0开始),最多取多少条limit

//从第一个(0相当于数组的下标,指向的是第一个数)开始取offset 0,最多取两个limit 2
select * from books order by bid limit 2 offset 0;
//从第3个开始取offset 2,最多取两个limit 2
select * from books order by bid limit 2 offset 2;

很容易实现的一个分页功能, 展示一个列表,每页一共10条记录

取第 x 页,limit 2 offset (x - 1) * 2

select * from 表 where条件 order by 排序limit 10 offset 0; 第一页

select * from 表 where条件 order by 排序limit 10 offset 10; 第二页

select * from 表 where条件 order by 排序limit 10 offset 20; 第三页

1.3 更新(Update)

1. 通过where子句,找出符合条件的所有记录(下一步的更新只会更新这些记录)

2. 通过set语句对这些记录中的一个或者多个字段更新

-- 更推荐使用,因为上面两个属于bid主键PK和name是UQ
update books set total = 100 where bid = 7;
update books set total = 101 where name = '左传';
-- 不太推荐使用,因为total = 10的记录有很多,可能会把其他的也修改了
update books set total = 102 where total = 10;
update books set total = 103 where current = 5;
--
update books set current = 0; --没有设置where语句,所有记录的current都会被修改为0;

1.4 删除(Delete)

先通过where条件筛选出记录,删除这些满足条件的记录

delete from books where bid > 3; -- 删除所有bid大于3的记录
delete from books where bid = 2;-- 删除所有bid=2的记录
delete from books; 没有设置where条件,则所有记录都会被删除

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值