diff --git "a/06 \351\231\210\345\277\227\344\274\237/20231018.md" "b/06 \351\231\210\345\277\227\344\274\237/20231018.md" new file mode 100644 index 0000000000000000000000000000000000000000..a9155d01d8c852c82e71dc6af7ef8b8df930964b --- /dev/null +++ "b/06 \351\231\210\345\277\227\344\274\237/20231018.md" @@ -0,0 +1,255 @@ +## 索引 + +索引(index)是帮助MySQL高效获取数据的数据结构 + +#### 优点 + +降低CPU的消耗 + +#### 缺点 + + 降低了 INSERT、UPDATE、DELETE 速度 + +### 索引的分类 + +单列索引:一个索引建立在一个列上,一张表可以拥有多个单列索引 + +- 普通索引:单纯地为了提高搜索效率 index +- 唯一索引:unique index,唯一索引只能够建立在数据不重复的列上 ,唯一约束 ,不能重复,可以null,有多个唯一索引 +- 主键索引:primary key唯一性、非空,主键约束 ,不能重复,也不能null,一个只能有一个主键 + +联合索引:可以同时为多个列创建一个索引 + +### 单列索引 + +#### 创建索引(普通索引) + +这是最基本的索引,它没有任何限制。它有以下几种创建方式: + +方式一:直接在已有表中创建索引 + +```sql +create index 索引名 on 表名(列名) -- 直接删除索引 drop index 索引名 on 表名; 这种不能用来创建主键索引 +``` + +方式二:修改表结构追加普通索引 + +```sql +alter table 表名 add index 索引名(列名); -- 修改表结构删除索引 alter table 表名 drop index 索引名; +``` + +方式三:创建表的时候直接指定 + +```sql +create table 表名( + aaa int primary key, + bbb varchar(20), + index 索引名 (列名) -- 以这种模式定义的索引,可以不指定索引名称。 + primary key(列名) +); +``` + +#### 查看表的索引 + +```sql +show index from 表名; +``` + +可以查看到创建在表上的所有索引名称。 + +#### 删除索引 + +```sql +drop index 索引名 on 表名; +``` + +并且删除表时,会一并删除表上的全部索引。 + +```sql +alter table 表名 drop index 索引名; +``` + +#### 唯一索引:建立列的唯一约束时,会自动创建唯一的索引,索引名就是列名 + +它与前面的普通索引类似,不同的就是:索引列的值必须唯一,但允许有空值。如果是组合索引,则列值的组合必须唯一。它有以下几种创建方式 + +```mysql +create unique index 索引名 on 表名(列名); -- 创建普通索引的基础上。多了unique关键字 +``` + + 在已存在的表上追加唯一索引 + +```mysql +alter table 表名 add unique 索引名 (列名) +``` + + 创建表的时候直接指定 + +```mysql +create table tc_9( + aaa int primary key, + bbb varchar(20), + unique [INDEX] 索引名 (列名) -- 唯一索引,一定有索引名,index 可以省略 +); + +-- 唯一索引和唯一约束 语法还是 有些区别 +create table tc_9( + aaa int primary key, + bbb varchar(20), + tel char(11), -- unique not null, + unique (tel) -- unique(列名) -- 约束是没有 索引名 和 index 关键字的 +); +``` + +**删除唯一索引的方法与删除普通索引相同。** + + +#### 主键索引 与 index 关键字没有关系 + +主键索引:它是一种特殊的唯一索引,不允许有空值。一般是在建表的时候指定了主键,就会创建主键索引, CREATE INDEX不能用来创建主键索引,使用 ALTER TABLE来代替。 + +创建主键索引,就是创建主键约束 + +```sql +drop table if exists tc_10; +create table tc_10( + aaa int primary key, + bbb varchar(20), + ccc datetime +); +create table tc_10( + aaa int, + bbb varchar(20), + ccc datetime, + primary key(aaa) +); +create table tc_10( + aaa int, + bbb varchar(20), + ccc datetime +); +alter table tc_10 add primary key(aaa); +``` + +删除主键 + +可以使用 ALTER 命令删除主键: index + +```sql +alter table 表名 drop primary key; +``` + +删除主键时只需指定PRIMARY KEY,但在删除索引时,你必须知道索引名。而不能使用删除普通索引的方法来删除主键索引。 + +```sql +-- 这都是错误的。 +drop index PRIMARY on tc_10; +drop primary key on tc_10; +``` + +### 联合索引 + +```sql +create index 索引名 on 表名(列名1,列名2....) -- 普通的联合索引 +create unique index 索引名 on 表名(列名1,列名2....) -- 联合唯一索引 +``` + +*执行原则:最左前缀法则 + +如果使用了联合索引,要遵守最左前缀法则。 + +最左前缀法则指的是查询从索引的最左列开始,并且不跳过索引中的列。如果跳跃某一列,后面的字段索引失效。 + +## 作业 + +执行查询文件tb_user.sql,数据准备好了之后,完成如下需求: + +```mysql +-- 1.name字段为姓名字段,该字段的值可能会重复,为该字段创建索引。 + +create index inx_name on tb_user(`name`); + +show index from tb_user; + +explain select `name` from tb_user; + +-- 2. phone手机号字段的值,是非空,且唯一的,为该字段创建唯一索引。 + +create unique index inx_phone on tb_user(phone); + +show index from tb_user; + +explain select phone from tb_user; + +-- 3. 为profession、age、status创建联合索引。 + +create index inx_user on tb_user(profession,age,`status`); + +show index from tb_user; + +explain select profession,age,`status` from tb_user; + +-- 4. 为email建立合适的索引来提升查询效率。 + +create index inx_email on tb_user(email); + +show index from tb_user; + +explain select email from tb_user; + +-- 5. 查看tb_user表的所有的索引数据。 + +show index from tb_user; +``` + +```mysql +delimiter // +create procedure pro_v() +begin + declare i int default 1; + start transaction; + while i<=100000 do + insert into zen values(null,(select concat + (mid('文徐李悠金郑钱黄肖罗将刘钟朴沈梁西林纱名平周方韩张章',floor(rand()*26+1),1), + substr('龙铉维知志多礼夏井子元采一泰太辰成在廷昇祯精彩宥',floor(rand()*24+1),1), + substr('馥辰志浩娜桃南一容祐英月喻元寅玟源叶演领',floor(rand()*20+1),1))), + (select mid('男女',floor(rand()*2+1),1)), + (select 100+i), + (select '爱好')); + set i=i+1; + end while; + commit; +end // + +call pro_v(); + +``` + +```mysql +use biao; +create table emlopyee( + id int primary key auto_increment, + namc char(3), + sex char(1) +); +drop procedure nam; +delimiter // + create procedure nam() + begin + declare i int default 0; + declare a varchar(3); + declare b varchar(1); + while i < 10 do + set a= CONCAT( +substring('赵钱孙李周吴郑王冯陈褚卫蒋沈韩杨朱秦尤许何吕施张孔曹严华金魏陶姜戚谢邹喻柏水窦章云苏潘葛奚范彭郎鲁韦昌马苗凤花方俞任袁柳',floor(rand()*60+1),1), +substring('伟刚勇毅俊峰强军平保东文辉力明永健世广志义兴良海山仁波宁贵福生龙元全国胜学祥才发武新利清飞彬富顺信子杰涛昌成康星光天达安岩茂进林有坚和彪博诚先敬震振壮会思群豪心邦承乐绍功松善厚庆磊民友裕河哲江超浩亮政谦亨奇固之轮翰朗伯宏言若鸣朋斌梁栋维启克伦翔旭鹏泽晨辰士以建家致树炎德行时泰盛',rand()*139+1,1), +substring('伟刚勇毅俊峰强军平保东文辉力明永健世广志义兴良海山仁波宁贵福生龙元全国胜学祥才发武新利清飞彬富顺信子杰涛昌成康星光天达安岩茂进林有坚和彪博诚先敬震振壮会思群豪心邦承乐绍功松善厚庆磊民友裕河哲江超浩亮政谦亨奇固之轮翰朗伯宏言若鸣朋斌梁栋维启克伦翔旭鹏泽晨辰士以建家致树炎德行时泰盛',rand()*139+1,1)); + set b= substring('男女',floor(rand()*2+1),1); + insert into emlopyee values(null,a,b); + set i= i+1; + end while; + end // +delimiter; +call nam(); +``` + diff --git "a/06 \351\231\210\345\277\227\344\274\237/20231019.md" "b/06 \351\231\210\345\277\227\344\274\237/20231019.md" new file mode 100644 index 0000000000000000000000000000000000000000..a4bd8b248b63313de73eef6a834f6160eceb523d --- /dev/null +++ "b/06 \351\231\210\345\277\227\344\274\237/20231019.md" @@ -0,0 +1,173 @@ +## 事务 + +### 事务的特性 + +原子性、一致性、隔离性、持久性 + +### 事务操作 + +mysql中事务默认是隐式事务,执行insert、update、delete操作的时候,数据库自动开启事务、提交或回滚事务 + +是否开启隐式事务是由变量autocommit控制的 + +所以事务分为**隐式事务**和**显式事务** + +#### 隐式事务 + +事务自动开启、提交或回滚,比如insert、update、delete语句,事务的开启、提交或回滚由mysql内部自动控制的。 + +查看变量autocommit是否开启了自动提交 + +#### 显式事务 + +事务需要手动开启、提交或回滚,由开发者自己控制。 + +```mysql +-- 显示所有的系统变量 +show variables; + +-- 查看autocommit状态 +show variables like 'autocommit'; + +-- 显式事务(手动提交,关闭系统自动) +set autocommit=off; +set autocommit=0; + +rollback; -- 撤销,可以保留数据 +commit; -- 提交数据 + +-- 隐式事务(自动提交,开启系统自动) +set autocommit=on; +set autocommit=1; + +rollback; -- 撤销,不保留数据,因为系统已经自动commit +``` + +```mysql +-- 开启事务 +start transaction; +-- 结束事务 +rollback / commit; +``` + +### savepoint关键字 + +可以将一大批操作分为几个部分,然后指定回滚某个部分。 + +```mysql +-- 在事务中途使用 +savepoint 保存名; + +-- 追溯回去 +rollback to 保存名; +``` + +### 只读事务 + +表示在事务中执行的是一些只读操作,如查询,但是不会做insert、update、delete操作,数据库内部对只读事务可能会有一些性能上的优化 + +```mysql +start transaction read only; +``` + +#### 脏读 + +#### 读已提交 + +#### 可重复读 + +#### 幻读 + +### 隔离级别 + +隔离级别分为4种: + +```mysql +读未提交:READ-UNCOMMITTED +读已提交:READ-COMMITTED +可重复读:REPEATABLE-READ +串行:SERIALIZABLE +``` + + + +## 作业 + +```mysql +-- 部门表 +create table dept( + deptno int primary key auto_increment, -- 部门编号 + dname varchar(14) , -- 部门名字 + loc varchar(13) -- 地址 +) ; +-- 员工表 +create table emp( + empno int primary key auto_increment,-- 员工编号 + ename varchar(10), -- 员工姓名 - + job varchar(9), -- 岗位 + mgr int, -- 直接领导编号 + hiredate date, -- 雇佣日期,入职日期 + sal int, -- 薪水 + comm int, -- 提成 + deptno int not null, -- 部门编号 + foreign key (deptno) references dept(deptno) +); +insert into dept values(10,'财务部','北京'); +insert into dept values(20,'研发部','上海'); +insert into dept values(30,'销售部','广州'); +insert into dept values(40,'行政部','深圳'); +insert into emp values(7369,'刘一','职员',7902,'1980-12-17',800,null,20); +insert into emp values(7499,'陈二','推销员',7698,'1981-02-20',1600,300,30); +insert into emp values(7521,'张三','推销员',7698,'1981-02-22',1250,500,30); +insert into emp values(7566,'李四','经理',7839,'1981-04-02',2975,null,20); +insert into emp values(7654,'王五','推销员',7698,'1981-09-28',1250,1400,30); +insert into emp values(7698,'赵六','经理',7839,'1981-05-01',2850,null,30); +insert into emp values(7782,'孙七','经理',7839,'1981-06-09',2450,null,10); +insert into emp values(7788,'周八','分析师',7566,'1987-06-13',3000,null,20); +insert into emp values(7839,'吴九','总裁',null,'1981-11-17',5000,null,10); +insert into emp values(7844,'郑十','推销员',7698,'1981-09-08',1500,0,30); +insert into emp values(7876,'郭十一','职员',7788,'1987-06-13',1100,null,20); +insert into emp values(7900,'钱多多','职员',7698,'1981-12-03',950,null,30); +insert into emp values(7902,'大锦鲤','分析师',7566,'1981-12-03',3000,null,20); +insert into emp values(7934,'木有钱','职员',7782,'1983-01-23',1300,null,10); + +-- 1、列出最低薪金大于1500的各种工作。 +-- +select distinct job from emp where sal > 1500; +-- 2、列出在部门 "销售部" 工作的员工的姓名,假定不知道销售部的部门编号。 +-- +select * from emp where (deptno not in(10,20,40)); +-- 3、列出薪金高于公司平均薪金的所有员工。 +-- +select * from emp where sal > (select avg(sal) from emp); +-- 4、列出与"周八"从事相同工作的所有员工。 +-- +select * from emp where job = ( +select job from emp where ename = '周八') and ename != '周八'; +-- 5、列出薪金等于部门30中员工的薪金的所有员工的姓名和薪金。 +-- +SELECT * from emp where sal in +(select sal from emp where deptno = 30); +-- 6、列出薪金高于在部门30工作的所有员工的薪金的员工姓名和薪金。 +-- +select * from emp where sal> +(select max(sal) from emp where deptno = 30); +-- 7、列出在每个部门工作的员工数量、平均工资、平均服务年限。 +-- +select count(ename),avg(sal),avg(timestampdiff(year,hiredate,now())) from emp group by deptno; +-- 8、列出所有员工的姓名、部门名称和工资。 +-- +select ename,job,sal,dname from emp e,dept d where e.deptno=d.deptno; +-- 9、列出所有部门的详细信息和部门人数。 +-- +select distinct dname,loc,count(*) over(partition by dname) from emp e,dept d where e.deptno=d.deptno; +-- 10、列出各种工作的最低工资。 +-- +select min(sal) from emp group by deptno; +-- 11、列出各个部门的 经理 的最低薪金。 +-- +select min(sal) from emp where job = '经理' group by deptno; +-- 12、列出所有员工的年工资,按年薪从低到高排序。 +-- +select *,(sal+ifnull(comm,0))*365 a from emp ORDER BY a asc; +``` \ No newline at end of file