From f057032566039f26bbe81b3030b1136a366b448f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9F=A9=E9=9C=87=E6=B4=8B?= <11785166+hzyai77@user.noreply.gitee.com> Date: Wed, 25 Oct 2023 14:34:57 +0000 Subject: [PATCH] =?UTF-8?q?=E9=9F=A9=E9=9C=87=E6=B4=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 韩震洋 <11785166+hzyai77@user.noreply.gitee.com> --- .../20231024.md" | 732 ++++++++++++++++++ 1 file changed, 732 insertions(+) create mode 100644 "40 \351\237\251\351\234\207\346\264\213/20231024.md" diff --git "a/40 \351\237\251\351\234\207\346\264\213/20231024.md" "b/40 \351\237\251\351\234\207\346\264\213/20231024.md" new file mode 100644 index 0000000..a859c12 --- /dev/null +++ "b/40 \351\237\251\351\234\207\346\264\213/20231024.md" @@ -0,0 +1,732 @@ +## 数值函数 + +```mysql +-- 随机数 +select rand(); -- 返回一个0-1之间的浮点数 +select floor(rand()); -- 将返回值向下取整 +select ceil(rand()); -- 将返回值向上取整 + +-- 求余 +select mod(5,2); -- 求10/5的余数 + +-- 四舍五入 +select round(3.1415926); -- 四舍五入变整数 +select round(3.1415926,3); -- 保留3位小数(四舍五入) + +``` + + + +## 字符串函数 + +```mysql +select length('apple'); -- 返回该字符串长度 + +select concat('黎','俊','杨'); -- 拼接括号内所有字符串 + +select replace('我是你爸爸','爸爸','儿子'); -- 替代文字,将爸爸替换成儿子 + +select lower('ABC'); -- 转小写 +select upper('abc'); -- 转大写 + +select lpad('apple',63,'x'); -- 在字符串前面填充x达到63个字符 +select rpad('apple',63,'x'); -- 在字符串后面填充x达到63个字符 + +select left('apple',2); -- 提取字符串前两位字符 +select right('apple',2); -- 提取字符串后两位字符 + +select trim(' apple '); -- 去除字符串所有空格 +select ltrim(' apple ') -- 去除字符串前面的空格 +select rtrim(' apple ') -- 去除字符串后面的空格 + +select substring('apple',3,2) -- 从字符串第三位向后取值两个字符(下位从1开始) + +SELECT SUBSTRING_INDEX("www.w3schools.com", ".", 2); -- 返回第二个.之前的字符 + +``` + + + +## 日期函数 + +```mysql +select curdate(); -- 返回当前日期 +select curtime(); -- 返回当前时间 +select now(); -- 返回当前日期和时间 + +select year('2012-12-2'); -- 提取当前年份(需保证时间准确性) +select month('2012-12-2'); -- 提取当前月份(需保证时间准确性) +select day('2012-12-2'); -- 提取当前日期(需保证时间准确性) + +SELECT DATE_ADD(NOW(), interval 20 your/month/day); -- 返回当前时间经过20年/月/日的时间 + +select datediff('2022-12-2','2022-1-2'); -- 返回两个时间之间的天数 + +``` + + + +# 存储过程 + +```mysql +delimiter && -- 将分界符从;改为&& +create procedure one() -- 创建存储过程 +begin -- 开始语句 +select * from ljy; -- 准备执行的代码 +end && -- 结束存储过程 +delimiter; -- 将分界符从&&改为; + +call one; -- 调用过程 +``` + + + +## 参数 + +```mysql +set @admin='大脑斧'; -- 会话变量 + + +delimiter && +create procedure one() +begin +declare name varchar(10); -- 创建局部变量(只能创建和生效在procedure过程里面) +set name = '小明'; -- 给局部变量赋值 +end && +delimiter; + + +delimiter && +create procedure one(in myid int,out myname varchar(100)) -- in 入参,out 出参 inout 入参+出参 +begin +select last_name into myname from employees where employee_id=myid; -- 在查询的字段后面写into+赋值变量(给局部变量赋值) +end && +delimiter; + +call one(100,@name); -- 输入参数(参数之间需相互对应) + +select @name; -- 查询参数 +``` + + + +## 分支结构 + +### if + +```mysql +drop procedure test_if_case; +delimiter // +CREATE PROCEDURE test_if_case( +in fenshu int +) +begin +if fenshu>90 then select 'A'; -- 以if开头 then为执行语句 +elseif fenshu>80 then select 'B'; -- 当有多个判断条件用elseif连接 +elseif fenshu>60 then select 'C'; +else select 'D'; -- 最后一个条件用else +end if; -- 结束用end if +END // +delimiter ; + +call test_if_case(99); +``` + + + +### case + +```mysql +drop procedure test_if_case; +delimiter // +CREATE PROCEDURE test_if_case( +in fenshu int +) +begin +case -- 以case开头 +when fenshu>90 then select 'A'; -- 用when连接各个判断条件,then为执行语句 +when fenshu>80 then select 'B'; +when fenshu>60 then select 'C'; +else select 'D'; -- 最后一个条件用else +end case; -- 结束用end case +END // +delimiter ; + +call test_if_case(99); +``` + + + +## 循环 + +leave --直接跳出循环(需要搭配循环标识符使用) + +iterate --跳过此次循环(需要搭配循环标识符使用) + + + +### loop + +#### 死循环 + +```mysql +-- 计算10以内数字之和 +drop procedure li; + +delimiter // +create procedure li(in num int) + begin + declare i int default 1; -- 创建一个名为i的变量,并赋值为1; + declare s int default 0; -- 创建一个名为s的变量,并赋值为0; + x:loop -- 开始loop循环 + if i<=num then + set s=s+i; + set i=i+1; + elseif i>num then + leave x; -- 跳出该循环 + end if; + end loop x; -- 结束循环 + select s; + end // +delimiter ; + +call li(10); +``` + + + +### while + +#### 带有条件的循环(类似于java循环) + +```mysql +-- 计算10以内数字之和 +drop procedure li; + +delimiter // +create procedure li(in num int) + begin + declare i int default 1; + declare s int default 0; + x:while i<=num do -- 开始while循环 + set s=s+i; + set i=i+1; + end while x; -- 结束while循环 + select s; + end // +delimiter ; + +call li(10); +``` + + + +### repeat + +#### 先循环后判断条件 + +```mysql +-- 计算10以内数字之和 +drop procedure li; + +delimiter // +create procedure li(in num int) + begin + declare i int default 1; + declare s int default 0; + repeat -- 开始repeat循环 + if i<=num then + set s=s+i; + set i=i+1; + end if; + until i>num end repeat; -- 结束repeat循环 + select s; + end // +delimiter ; + +call li(10); +``` + + + +## 游标 + +```mysql +-- 利用游标查询emp中每个员工的姓名(单独输出) +drop procedure pro; + +delimiter // +create procedure pro() +begin + declare x int default 0; + declare num int; + declare eename varchar(255); + declare ub cursor for select ename from emp; -- 定义一个名为ub的游标,后面跟查询语句的结果 + select count(ename) into num from emp; + open ub; -- 打开游标 + while x 30 and status = '0'; + +-- 解决 +explain select * from tb_user where profession = '软件工程' and age >= 30 and status = '0'; +``` + + + +## 索引失效情况 + +#### 索引列运算 + +```sql +explain select * from tb_user where substring(phone,10,2) = '15'; +``` + +#### 字符串不加引号 + +```sql +explain select * from tb_user where profession = '软件工程' and age = 31 and status = '0'; +explain select * from tb_user where profession = '软件工程' and age = 31 and status = 0; --失效 + +explain select * from tb_user where phone = '17799990015'; +explain select * from tb_user where phone = 17799990015; --失效 +``` + + + +#### 模糊查询 + +```sql +explain select * from tb_user where profession like '软件%'; +explain select * from tb_user where profession like '%工程'; -- 失效 +explain select * from tb_user where profession like '%工%'; -- 失效 +``` + +#### or连接条件 and + +用or分割开的条件, 如果or前的条件中的列有索引,而后面的列中没有索引,那么涉及的索引都不会被用到。 + +```sql +explain select * from tb_user where id = 10 or age = 23; +explain select * from tb_user where phone = '17799990017' or age = 23; + +--对age字段建立索引,再次执行 +create index idx_user_age on tb_user(age); +``` + +#### 数据分布影响 + +如果MySQL评估使用索引比全表更慢,则不使用索引。 + +```sql +-- 比较运算符范围查询 +select * from tb_user where phone >= '17799990005'; +select * from tb_user where phone >= '17799990015'; + +-- is null 与 is not null +explain select * from tb_user where profession is null; +explain select * from tb_user where profession is not null; +``` + + + +## SQL提示 + +```sql +select * from 表名 use index(索引名) where.... -- 建议 +select * from 表名 ignore index(索引名) where.... -- 忽略 +select * from 表名 force index(索引名) where.... -- 强制 +``` + + + +## 覆盖索引 + +尽量使用覆盖索引,减少select * 的使用。 + +那么什么是覆盖索引呢? 覆盖索引是指 查询使用了索引,并且需要返回的列,在该索引中已经全部能够找到 。 + +```sql +explain select id, profession from tb_user where profession = '软件工程' and age = 31 and status = '0' ; +explain select id,profession,age,status from tb_user where profession = '软件工程' and age = 31 and status = '0' ; +explain select id,profession,age,status,name from tb_user where profession = '软件工程' and age = 31 and status = '0' ; +explain select * from tb_user where profession = '软件工程' and age = 31 and status = '0'; +``` + +| Extra | 含义 | +| ------------------------ | ------------------------------------------------------------ | +| Using where; Using Index | 查找使用了索引,但是需要的数据都在索引列中能找到,所以不需要回表查询数据 | +| Using index condition | 查找使用了索引,但是需要回表查询数据 | + + + +## 单列索引与联合索引 + +到底是选单列索引还是联合索引? + +在业务场景中,如果存在多个查询条件,考虑针对于查询字段建立索引时,建议建立联合索引,而非单列索引。 + +-- + +## 索引设计原则 :索引方便查询的,影响插入。更新,删除 + +1). 数据量较大,且查询比较频繁的表。 100w + +2). 常作为查询条件(where)、排序(order by)、分组(group by)操作的字段。 + +3). 尽量选择区分度高的列,尽量建立唯一索引,区分度越高,使用索引的效率越高。 + +4). 如果是字符串类型的字段,字段的长度较长,可以针对于字段的特点,建立前缀索引。-- 分表 + +5). 尽量使用联合索引,减少单列索引,查询时,联合索引很多时候可以覆盖索引,节省存储空间,避免回表,提高查询效率。 + +6). 要控制索引的数量,索引并不是多多益善,索引越多,维护索引结构的代价也就越大,会影响增删改的效率。 + +7). 如果索引列不能存储NULL值,请在创建表时使用NOT NULL约束它。当优化器知道每列是否包含NULL值时,它可以更好地确定哪个索引最有效地用于查询。 + + + +# 事务 + +```mysql +-- 在mysql中事务是默认开启状态 + +select * from employee; + +show variables like 'autocommit'; -- 查看事务状态 + +set autocommit =0; -- 事务关闭 +set autocommit =off; -- 事务关闭 + +set autocommit =1; -- 事务开启 +set autocommit =on; -- 事务开启 + +select * from employee; + +delete from employee ; + +rollback; -- 回滚 + +start transaction; -- 开始一次临时事务,将在第一次回滚的时候失效 + +delete from employee where id=1; +savepoint t_1; -- 设置一个存档点 +delete from employee where id=2; +savepoint t_2; +delete from employee where id=3; +savepoint t_3; +delete from employee where id=4; +savepoint t_4; +delete from employee where id=5; + +rollback to part1; -- 回滚到一个存档点 + +commit; -- 提交事务 + +``` \ No newline at end of file -- Gitee