条件:创建学生表与老师表
-- 1.0 创建学生的表,并添加数据createtablestudent(stu_idintprimarykey,stu_namevarchar(5)notnullunique,stu_ageintnotnull);insertintostudent(stu_id,stu_name,stu_age)values(24,"小明",18);insertintostudent(stu_id,stu_name,stu_age)values(25,"小王",19);insertintostudent(stu_id,stu_name,stu_age)values(26,"小张",20);insertintostudent(stu_id,stu_name,stu_age)values(27,"小黄",21);insertintostudent(stu_id,stu_name,stu_age)values(28,"小红",22);select*fromstudent;-- 2.0 创建老师表createtableteacher(tea_idintprimarykey,tea_namevarchar(5)notnullunique,tea_ageintnotnull);insertintoteacher(tea_id,tea_name,tea_age)values(1,"王老师",40);insertintoteacher(tea_id,tea_name,tea_age)values(2,"黄老师",41);insertintoteacher(tea_id,tea_name,tea_age)values(3,"张老师",42);insertintoteacher(tea_id,tea_name,tea_age)values(4,"李老师",43);insertintoteacher(tea_id,tea_name,tea_age)values(5,"丁老师",44);一 : 增删改查
1.0 数据库的增删改查
-- 使用数据库: useuse数据库的名字;-- 1.0 增 create-- 语法:createdatabase数据库的名字;-- 列子;createdatabasedb_text190-- 2.0 删除数据库 drop-- 语法:dropdatabaseifexists数据库的名字;-- 列子dropdatabasedb_text1;dropdatabaseifexistsdb_text1;-- 3.0 改 : 一般修改数据库的字符集 alteralterdatabase数据库的名字charactersetutf8;-- 4.0 查询数据库 showshowdatabases;2.0 数据库的表的增删改查
-- 1.0 增 create-- 语法:createtable表的名字(字段 类型(长短)约束,);-- 常见的类型int数值类型char不可变字符串varchar可变字符串-- 常见的字段primarykey主键,也就是相当与非空加上不可重复约束notnull非空约束unique不可重复约束-- 列子: 创建一个学生表,createtablestudent(stu_namevarchar(5)notnullunique,stu_ageintnotnull,stu_genderchar(2)notnull);-- 2.0 删除数据表 drop-- 语法:droptableifexists表的名字;-- 列子:droptableifexistsstudents;-- 3.0 修改: alter-- 语法 :altertable表的名字 改的类型 ;-- 改的类型:renametosetadddropchangemodify-- 列子:-- 1.0 将我们的学生表的名字改为老师的名字altertablestudentrenametoteacher;-- 2.0 将我们表的字符集进行修改altertablestudentcharactersetutf8;-- 3.0 添加字段altertablestudentaddstu_genderchar(2)notnull;-- 4.0 修改字段(这里修改整个字段)altertablestudent change stu_name stu_heightdoublenotnull;-- 5.0 修改字段(这里修改的是我们字段类型)altertablestudentmodifystu_agedouble;-- 6.0 删除字段altertablestudentdropstu_age;# 4.0 查showtables; 查询所有的数据表desc表的名字; 查询表的结构3.0 表中的数据增删改查
-- 1.0 插入数据-- 语法:insertinto表的名字(各个类型)values(各个数据);-- 列子: 向我们的学生表中添加数据insertintostudent(stu_id,stu_name,stu_age)values(24,"小明",18);-- 2.0 删除数据-- 语法:deletefrom表的名字where条件;like这个关键字进行模糊匹配-- 列子:-- 1.0 删除我们表中性别全为男的数据deletefromstudentwherestu_gender='男';-- 2.0 删除我们表中年龄大于20的数据deletefromstudentwherestu_age>20;-- 3.0 改-- 语法:updata.....set.....-- 列子 :-- 1.0 将我们学生的id=24 的学生的姓名改成王五updatestudentsetstu_name="王五"whereid=24;-- 2.0 将id=23 的学生性别修改为'女' 并且他的名字修改为'李四'updatestudentsetstu_gender="女",stu_name="李四"whereid=23;-- 4.0 查-- 语法:select列from表的名字where/like条件;-- 列子:-- 1.0 查询我们表中的所有的数据 *select*fromstudent;-- 2.0 查询我们学生表中所有男生的数据select*fromstudentwherestu_gender='男';-- 3.0 查询我们学生表中年龄大于20的数据select*fromstudentwherestu_age>20;-- 4.0 查询我们学生表中学生名字包含字母0的数据 %select*fromstudentwherestu_name="%o%";-- 5.0 查询我们学生表中姓名第二个字母为o 的信息select*fromstudentwherestu_name="_o%";-- 6.0 查询我们学生表中表中的第一个字母为o 的信息select*fromstudentwherestu_name="o%";-- 7.0 查询学生姓名第一个字为'张'的学生信息select*fromstudentwherestu_name="张%";-- 8.0 查询我们表中女生并且女生的年龄大于20 的数据 || 表示或 && 表示并且select*fromstudentwherestu_gender="女"&&stu_age>20;4.0 总结
| 数据库 | 数据库中的表 | 数据库中表的数据 | |
|---|---|---|---|
| 增 | create | create | insert into |
| 删 | drop | drop | delete from |
| 改 | alter | alter | update … set |
| 查 | show | show | select … from |
二 : 查询的扩展
1.0 字段与函数
-- 1.0 as: 对我们的字段取别名-- 列子-- 1.0 查询表中的出生日期是多少,并命名selectstu_name,2025-stu_ageas出生日期fromstudent;-- 2.0 distinct 消除重复行-- 将我们表中年龄重复的行消除selectdistinctstu_agefromstudent;-- 3.0 order by : 排序 , 升序用asc ,降序用desc-- 列子:-- 1.0 将我们表中的数据按照年龄进行升序排列select*fromstudnetorderbystu_genderasc;-- 2.0 先按照性别升序排列,然后性别相同的 按照年龄降序排列select*fromstudentorderbystu_genderasc,stu_agedesc;-- 4.0 聚合函数count(): 统计总数max(): 最大值min(): 最小值sum(): 总数avg(): 平均值-- 列子-- 1.0 统计学生的总数selectcount(stu_name)fromstudent;-- 2.0 统计性别为男的总数selectcount(stu_name)wherestu_gender='男'fromstudent;-- 3.0 统计表中年龄的最大值selectmax(stu_age)fromstudent;-- 4.0 计算学生年龄的总和selectsum(stu_age)fromstudent;-- 5.0 日期函数sysdate()获取当前时间now()获取当前时间selectsysdate();selectnow();-- 列子: 向我们表中插入时间,时间就用我们当前的时间insertintostudent(stu_name,stu_time)values("小明",now());-- 6.0 字符串函数concat(字段1,字段2,...): 将我们字符串拼接成多列 upper(): 将字段中的值转换成大写 lower();将我们的字段转换成小写的 substring(字段,开始,截取的长短): 将我们的字符串进行截取-- 1.0 列: 将我们学生表中的学生的姓名和学生的性别拼接在一起selectconcat(stu_name,'-',stu_age)fromstudent;-- 2.0 列: 将我们学生表中的英文名字 转换成大写的selectupper(stu_name)fromstudent;-- 3.0 列: 将我们学生表中的电话号码 从第5位进行截取, 截取4位selectsubstring(stu_tel,5,4)fromstudent;2.0 分组查询与分页查询
-- 1.0 分组查询-- 语法: select 字段 from 表名 group by 字段;-- 列:-- 1.0 先对查询的学生信息按性别进行分组 , 然后统计每一组学生的个数selectstu_gender,count(stu_num)fromstusgroupbystu_gender;-- 2.0 对查询的学生的信息 按照性别进行分组 ,然后统计每一组的平均年龄selectstu_gender,avg(stu_age)fromstusgroupbystu_gender;-- 3.0 将我们学生的年龄进行分组(16,17,18,19 四组) , 统计每一组学生的个数 ,并进行排序selectstu_age,count(stu_num)fromstusgroupbystu_ageorderbystu_age;-- 4.0 学生按照年龄进行分组,统计每一组的人数, 筛选出当组人数大于1 的组, 再按照年龄升序显示出来selectstu_age,count(stu_num)fromstusgroupbystu_agehavingcount(stu_num)>1orderbystu_age;-- 5.0 查询性别 位'男' 的学生, 按照年龄进行分组, 然后分别统计每组的人数, 再筛选出当前组人数 >1 的组 ,再按年龄升序显示出来selectstu_age,count(stu_num)fromstuswherestu_gender='男'groupbystu_agehavingcount(stu_num)>1orderbystu_age;-- 2.0 分页查询当数据表中的记录比较多的时候,如果一次性全部查询出来显示给用户,用户的可读性/体 验性就不太好,因此我们可以将这些数据分页进行展示1.0分页查询怎么实现?(MySQL 实际语法) MySQL 使用关键字:LIMIToffset,sizeoffset:从第几条开始 size:查多少条(每页多少条)2.0案例: 🔹2.1.查询前10条(第一页)SELECT*FROMstudentLIMIT0,10;意思:从第0条开始,查10条。 🔹2.2查询第二页(假设每页10条) 第二页offset=(page-1)*size=(2-1)*10=10SELECT*FROMstudentLIMIT10,10;🔹2.3第 N 页的通用写法SELECT*FROMstudentLIMIT(page-1)*pageSize,pageSize;如果你页面传 page=3,pageSize=10:SELECT*FROMstudentLIMIT20,10;3.0面试官常问:分页为什么要用LIMIT? 你可以这样回答:LIMIT只取一小段数据,避免扫描太多行,提高查询效率。4.0再加一个企业常用分页(带排序)SELECT*FROMstudentORDERBYstu_idDESCLIMIT20,10;5.0面试加分题:分页查询慢怎么优化? 给排序字段加索引(最重要) 使用覆盖索引注意:SQL语句书写和执行顺序 书写:select、form、where、group by、having、order by、limit 执行:from、where、group by、having、select、order by、limit (后续还会学到join,那么它的优先级要高于form)
3.0 数据表的关联关系与外键约束
关联关系:
通过关联关系, 我们可以建立 表与表之间的关系。
常见的关联关系 : 一对一 ,一对多, 多对一 ,多对多
外键约束
-- 1.0 概念:就是一张表的外键与另一张表的主键进行关联-- 2.0 创建一个班级表,其中含有id,namecreatetableclass(idintprimarykeyauto_increment,namechar(10)notnullunique,);-- 3.0 创建一个学生表,其中有name,gender,age,cid,并在外面添加外键约束,使得班级表中的id与学生表中的cid进行关联createtablestudent(namechar(5)primarykey,genderchar(2)notnull,ageint,cidint;);altertablestudentaddconstraintcl_stforeignkey(cid)referencesclass(id);altertable添加外键约束表的名字addconstraint自己起的关联的名字foreignkey(列的名字)references表的名字(关联字段);-- 4.0 添加数据insertintoclass(id,name)values(1,"java001班");insertintoclass(id,name)values(2,"java002班");insertintostudent(name,gender,age,cid)values("小明","男",18,1);insertintostudent(name,gender,age,cid)values("小王","女",18,1);insertintostudent(name,gender,age,cid)values("小潘","男",19,2);-- 5.0 进行查询select*fromclass;select*fromstudent;级联操作
-- 1.0 注意:我们的班级表 现在和学生表进行关联了,我们不可以直接进行修改班级表中的信息, 比如:updateclasssetid=5wherename="java001班"; 我们想要将java001班的id修改成5,这样直接进行修改是不对的。-- 2.0 方法一:三步走修改关联班级表中的id第一:将我们的学生表中的cid全部修改成NULLupdatestudentsetcid=NULLwherecid=1;第二:修改班级表中的idupdateclasssetcid=5wherename="java001班"; 第三:将我们学生表中的cid=NULL值进行改回来updatestudentsetcid=5wherecidisNULL;4.0 连接查询与子查询
介绍与前提的数据准备
-- 1.0 创建班级信息表,并添加数据createtableclass(idintprimarykey,`name`varchar(50)notnull;);insertintoclass(id,`name`)values(1,"java班级");insertintoclass(id,`name`)values(2,"运维班级");insertintoclass(id,`name`)values(3,"python大数据班级");-- 2.0 创建学生信息表,添加外键使得其中的cid与class中的id进行关联,最后并添加数据createtablestudent(namevarchar(5),-- 注意这里不可以用name作为主键ageintnotnull,genderchar(1)notnull,cidint);altertablestudentaddconstraintst_clforeignkey(cid)referencesclass(id);insertintostudent(name,age,gender,cid)values("小明",18,"男",1);insertintostudent(name,age,gender,cid)values("小王",18,"女",2);insertintostudent(name,age,gender,cid)values("小潘",19,"男");insertintostudent(name,age,gender,cid)values("小小",19,"女");-- 3.0 inner join 内连接 :就是两张表联合进行查询,但是只能是显示相互对应共同的部分语法:select*from表1的名字innerjoin表2的名字where表1的名字.列名=表2的名字.与其关联的名字select*fromstudentinnerjoinclasswherestudent.cid=class.id;-- 4.0 左连接和右连接查询select*fromstudentrightjoinclasswherestudent.cid=class.id;select*fromstudentleftjoinclasswherestudent.cid=class.id;左连接和右连接(left join ,right join)
1. 左连接(LEFT JOIN)
左连接是:以左表为主,先取左表全部数据,再匹配右表;右表匹配不到的用 NULL 补上。
▶一句话版本(面试最常用):
LEFT JOIN 保留左表全部数据,右表能对上就显示,对不上就 NULL。
2. 右连接(RIGHT JOIN)
右连接是:以右表为主,先取右表全部数据,再匹配左表;左表匹配不到的用 NULL 补上。
▶一句话版本:
RIGHT JOIN 保留右表全部数据,左表对不上就 NULL。
✅ 你可以举个 5 秒钟的例子(面试官喜欢)
假设两个表:
student
| id | name |
|---|---|
| 1 | 张三 |
| 2 | 李四 |
| 3 | 王五 |
score
| id | score |
|---|---|
| 1 | 90 |
| 3 | 80 |
LEFT JOIN:先保留 student 的全部 → 对不上 NULL
SELECTs.id,s.name,sc.scoreFROMstudent sLEFTJOINscore scONs.id=sc.id;结果:
| id | name | score |
|---|---|---|
| 1 | 张三 | 90 |
| 2 | 李四 | NULL |
| 3 | 王五 | 80 |
RIGHT JOIN:先保留 score 的全部 → 对不上 NULL
SELECTs.id,s.name,sc.scoreFROMstudent sRIGHTJOINscore scONs.id=sc.id;结果:
| id | name | score |
|---|---|---|
| 1 | 张三 | 90 |
| 3 | 王五 | 80 |
student 没有 id=2 的成绩,也不会显示。
三:存储过程
SQL指令的执行过程
编写sql指令——发送给sql服务器——服务器处理sql指令——服务器执行sql指令——整体结果发送给客户端——客户端收到
SQL指令流程中存在的问题
1.0 相同的SQL要重发一样的流程
2.0 如果要一次性执行多个SQL指令,那么第二个指令需要第一个指令的执行结果作为参数
存储过程的介绍
定义:
对完成特点功能的SQL指令集进行封装,客户端直接调用这个名字,直接就可以执行结果。
存储过程的优缺点:
优点:
高性能
- 预编译执行,减少解析开销。
- 减少网络传输(多个SQL合并调用)。
逻辑封装与复用
- 业务逻辑封装,统一维护,减少代码冗余。
- 增强数据安全性(通过权限控制隐藏细节)。
事务控制
- 方便实现多步骤事务,保证一致性
缺点:
调试维护困难
- 调试工具有限,逻辑复杂时排查效率低。
移植性差
- 语法与数据库绑定,迁移到其他数据库(如PostgreSQL)需重写。
扩展性限制
- 不利于水平扩展(集群中存储过程可能跨节点问题)。
- 增加数据库负载,可能成为单点瓶颈。
版本管理复杂
- 与应用程序代码分离,需单独管理版本和依赖。
创建,调用存储过程
-- 1.0 语法:createprocedure名字(in/out参数名字)beginsql指令end;-- 2.0 定义一个存储过程来实现两位数的加法createprocedurepro_text1(inaint,inbint,outcint)beginsetc=a+b;-- set 的意思就是定义变量的意思end;-- 3.0 调用存储过程set@m=0;callpro_text1(3,2,@m)select@mfromdual;-- 为啥要从dual 中进行查询存储过程中变量的使用
-- 1.0 局部变量的定义: 在存储过程的内部,然后用declare开始,定义在存储过程的最开始-- 2.0 定义一个存储过程,变量要使用局部变量,需要实现 a*a+b*2createprocedurepro_text2(inaint,inbint,outcint)begin-- declare a int default 1; 这里为啥不管声明-- declare b int default 2;seta=a*a;setb=b*2;setc=a+b;end;-- 3.0 定义用户变量: 用set 和@ 即可set@m=0;callpro_text2(2,3@m)select@mfromdual;-- 4.0 无论是局部变量还是全局变量,我们都要用set 对变量的值进行修改-- 5.0 查询结果赋值给变量: 用select ... into ... 语句-- 定义一个存储过程,将我们从表中查询到的数据赋值给他,最后并调用这个存储过程createprocedurepro_text3(outcint)beginselectcount(stu_name)intocfromstudents;end;callpro_text3(@n);select@nfromdual;-- 6.0 注意:建议少用用户变量存储过程中的参数:in / out / inout
-- 1.0 in 参数:输入参数-- 创建一个存储过程来向表中添加学生的信息createprocedurepro_text4(innamechar(5),inageint,ingenderchar(2))beginselectintostudents(stu_name,stu_age,stu_gender)values(name,age,gender)end;callpro_text4("小明",19,"男");-- 2.0 out : 将存储过程的结果,返回给调用者-- 创建存储过程:根据我们学生的学号来查询学生的姓名createprocedurepro_text5(insidvarchar(11),outsnamevarchar(5))beginselectstu_idintosidfrompro_text5wherestu_name=sname;end;set@sname='';callpro_text5('12345',@sname);seltct@snamefromdual;-- 3.0 inout 输入输出参数 :实际中不建议使用存储过程中的流程控制语句
分支语句
-- 1.0 单分支: if (条件判断 then sql) end if-- 创建一个存储过程,如果变量的值为1 ,那么就表中添加一个数据createprocedurepro_text6(inaint)beginifa=1theninsertintostudents(name,age)values("小潘",19);endif;end;-- 2.0 双分支: if (条件判断 then sql) (else sql ) end if;-- 创建一个存储过程,如果值=1,那么就添加班级数据。否则就添加学生数据createprocedurepro_text7(inaint)beginifa=1theninsertintoclasses(name,num)values("java001",45);elseinsertintostudents(name,age)values("小明",19);endif;end;-- 3.0 case 语句: (case 变量 ) (when 值1 then sql语句) (when 值2 then sql语句) ..... (end case);--createprocedurepro_text8(inaint)begincase2when1thenselectintostudent(name,age)values("小明",19);when2thenselectintoclass(name,num)values("java001",45)endcase;end;循环语句
-- 1.0 while 循环: (while 条件判断 do sql ) end while-- 创建一个存储过程,用来不断的向班级表中添加数据,且这个数据的数字部分是递增的createprocedurepro_text9(innumint)begindeclareiint;seti=1;whilei<numdoselectintoclass(name,remark)values(concat("java00",i));seti=i+1;endwhile;end;callpro_text9(4);-- 2.0 repeat 循环:和while的区别就是:把条件判断放到了最后,和end repeat 同行,且条件判断的前面加上 untilcreateprocedurepro_text10(innumint)begindeclareaint;seta=1;repeatinsertintoclasses(name,num)values(concat("java00",i));seti=i+1;untile i>numendrepeat;end;callpro_text10(4)-- 3.0 loop 要注意:停止循环时需要结合if语法:(myloop:loopsql)(if条件判断leavemyloopendif)(endloop)createprocedurepro_text11(innumint)begindeclareiint;seti=1;myloop:loopselectintoclasses(name,remark)values(concat("java00",i));seti=i+1;ifi=numleavemyloop;endif;endmyloopend;callpro_text11(5)存储过程管理
# 1.0 查询存储过程(存储过程是在某一个数据库中的,因此查询的时候要结合我们的数据库进行查询)show procedure status where db='mysql'# 查询存储过程的创建细节show create procedure mysql.pro_text1;# 2.0 修改存储过程# 3.0 删除存储过程drop procedure pro_text1四:触发器和游标
1.0 游标 (Cursor)
简答回答:
- 游标是用于在 MySQL 中逐行处理查询结果的一种机制。它通常用于需要逐条处理数据的场景,尤其是当我们需要处理一组结果集中的每一条记录时。
- 通过游标,我们可以在查询结果中“指针式”地移动,按需处理每一条数据。
举个例子:
- 假设你有一张订单表,你需要逐条检查每个订单的状态并进行一些计算,游标可以帮助你遍历这些订单进行逐行处理。
2.0 触发器 (Trigger)
简答回答:
- 触发器是一种特殊的存储过程,它会在对数据库表进行插入、更新或删除操作时自动执行。你可以用触发器来自动化一些操作,比如数据验证、日志记录等。
- 触发器会在指定的操作(如插入、更新、删除)发生之前或之后自动触发,保证在数据变更时执行额外的业务逻辑。
举个例子:
- 比如你有一个员工表,每次更新员工的工资时,你想记录一条工资变动日志。你可以设置一个触发器,在工资更新时自动插入一条变动记录到日志表中。
五:视图
1.0 :概念和作用
概念:
就是一张表或者多张表联合查询得到的一张虚拟表
作用:
安全性: 比如我通过视图,来查询多张表共同的需要的信息。而不是需要全部数据,保护了隐私的数据
简单性:视图结合了多张表的一些共同信息,我们用户查询视图就可以得到这些信息
不会占用数据文件
2.0 :创建视图
-- 1.0 创建视图的语法createview视图的名字AS我们要选择表中的特性-- 2.0 将学生表中的性别为 " 男 " 的信息提取出来,用视图createviewstu_genderASselect*fromstudentwheregender='男'-- 3.0 创建一个视图,里面包含我们的学生表中学生的年龄和 老师表中老师的年龄createviewview_text1asselectstu_agefromstudentunionselecttea_agefromteacher;-- 4.0 查询我们的视图中的内容select*from我们视图的名字;3.0 :视图数据的特性
查询操作: 在数据表中添加了新的数据,而且这个数据满足创建视图时的查询语句,通过查询视图也可以查询出新的语句。
当删除表中的某一个数据,满足视图的查询标准,那么这个数据也是从我们的视图中进行删除。
新增视图数据:如果在视图中添加数据,那么数据也是被添加到我们的数据表中。
删除视图数据:从视图中删除数据,那么这个数据在我们的数据表中也被删除了。
修改视图数据:通过修改视图中的数据,我们这个数据在数据表中也是被修改了。
4.0:视图的:查看,修改,删除
desc , alter , drop
# 1.0 查询视图的结构:descview_text1;# 2.0 修改视图方式一:用orreplace进行替换createorreplaceviewview_text1ASselect*fromstudentswherestu_gender='女'方式二:alterviewview_text1ASselect*fromstudentswherestu_gender='男'# 3.0 删除视图dropviewview_text1;六:索引
1.0 :索引的介绍
1.0 为啥会有索引:
当我们数据库中的表超过三百万条的时候,我们就需要设计索引了。
我们数据库的查询速度会随着我们数据量的增多而减缓。索引的出现就是提升我们数据库的查询速度的。
2.0 原理:
查询语句 > 索引(生成树结构) > 查询到我们表中的数据
就是先将我们数据表中的某一些值拿出来构造出一个数据表的目录。 当我们进行查询的时候,在这个目录中找到对应的数据
地址, 然后再根据地址找到我们表中的数据。 避免我们的全表扫描。
2.0 :索引的分类
主键索引:字段为primary key 。 添加这个字段的时候,会自动的生成这个主键索引
唯一索引:字段为 unique 。 添加这个字段的时候,会自动的生成唯一索引
普通索引:普通字段上创建的索引
组合索引:两个以上的字段创建的索引。
3.0:创建索引
# 1.0 创建唯一索引语法: create unique index 索引的名字 on 表的名字(字段的名字)create unique index index_text1 on students(stu_name);# 2.0 创建普通索引create index index_text2 on students(stu_name);# 3.0 创建组合索引create index index_text3 on students(stu_name,stu_id);# 4.0 查询我们的索引show indexfromstudents;4.0 :查询,删除索引
# 1.0 索引的使用:创建完索引后无需调用,当根据索引的列进行查询的时候,会自动的触发索引。 组合索引需要根据创建所有的所有字段进行查询时触发。# 2.0 查询我们数据表的索引show indexesfromindex_text1;show keysfromindex_text2;# 3.0 删除索引语法: drop index 索引的名字 on 表的名字; drop index index_text1 on student;5.0 :索引的使用总结
总结
-- 语法的总结想要的作用(index自己定义的index的名字)on表的名字(字段);1.0优点 索引大大降低了数据库服务器在执行查询操作时扫描的数据,提高查询效率 索引可以避免服务器排序,将随机 IO 编程顺序 IO2.0缺点 索引是根据数据表的列创建的,当数据表中数据发生 DML 操作时,索引页需要更新; 索引文件也会占用磁盘空间;3.0注意事项 数据表中数据不多时,全表扫描可能更快些,不要使用索引; 数据量大但是 DML 操作很频繁时,不建议使用索引; 不要在数据重复度高的列上创建索引(性别); 创建索引之后,要注意查询SQL语句的编写,避免索引失效。七:事务
1.0 :概念的介绍
一个完整业务的多个dml操作就是我们的事务,类比我们的银行进行转账,分为取钱然后扣钱的俩个操作。
就是一个完整的操作,比如完成银行的转钱(由转账和扣钱)。 就是完成一个业务的多个DML操作就是称之为数据库事务。
列子:以我们给别人进行转钱为列子
我们先要进行扣钱,然后再给别人转钱,不能只扣钱或者转钱。数据库事务就是多个操作的集合。
2.0:ACID特性(数据库的四大特性),面试高频
1.0 原子性: 就是多个DML的操作,要么同时成功和要么同时失败。
2.0 一致性:执行前后的数据必须都是一致的
3.0 隔离性:多个数据库事务这个是相互隔离的,互不干扰
4.0 持久性:事务完整之后,对数据库的操作是永久的。
3.0 :事务管理
1.0 自动提交
就是在mysql中,默认的DML指令是自动提交的,当我们执行DML操作的时候,会自动同步到数据库当中
2.0 事务管理
开启我们的事务,就是关闭自动提交。
(1) 执行 start transaction 开启事务
(2) 执行DML操作
(3) 出现异常的话,执行rollback回滚事务
(4) 都执行成功的话,最后commit提交事务
# 1.0 首先创建两张表:库存表和订单表createtabletb_text1(id1intprimarykey,name1varchar(10),num1intnotnull)createtabletb_text2(id2intprimary,name2varchar(10),num2intnotnull)insertintotb_text1(name1,num1)values('键盘',30);insertintotb_text1(name1,num1)values('耳机',40);# 2.0 开启事务starttransaction;# 2.0 减少库存updata tb_text1setnum=num-1wherename='鼠标';selectaaa# 这里一定会报错的# 3.0 增加订单insertintotb_text2(name,num)values('鼠标',1);# 4.0 事务回滚rollback;# 5.0 体检事务commit;4.0:隔离级别(读未提交,读已提交)
1.0 读未提交
就是脏读:客户端2读出的是客户端1 没有提交的数据。
2.0 读已提交
T2读的是T1提交后的数据,避免了脏读,但是可能出现不可重复读(虚读)
5.0 :隔离级别(可重复读,串行化)
1.0 可重复读
就是T2查询完数据之后,在事务结束之前其他的事务不能对其数据进行修改, 从而避免了不可重复读的情况。但是可能会出现幻读。
2.0 串行化
同时只允许一个事务对我们数据表进行修改,这样就避免了 脏读,虚度,幻读的情况。
6.0:设置 mysql 默认隔离级别
我们可以设置数据库默认的隔离级别来控制事务之间的隔离性。
数据库默认的隔离级别是可重复读
# 1.0 查看数据库默认的隔离级别select@@transaction_isolation;# 2.0 设置mysql默认的隔离级别setsessiontransactionisolationlevel<readcommitted>;会话 事务 隔离 级别八 : 主从复制和性能优化
1.0 主从复制 (Master-Slave Replication)
简答回答:
- MySQL 的主从复制是指将一个主数据库(Master)的数据实时复制到一个或多个从数据库(Slave)。主数据库处理写操作,而从数据库负责读取操作,从而实现负载均衡和数据冗余。
- 复制的实现通过二进制日志(binlog)来进行,主数据库将所有修改操作(如 INSERT、UPDATE、DELETE)记录在 binlog 中,从数据库通过读取并执行这些日志来保持数据同步。
举个例子:
- 假设你的网站有很多用户访问,你可以将读操作(查询)分配给从数据库,减轻主数据库的负担,从而提高系统的性能。
常见用途:
- 负载均衡:通过从数据库处理读操作来分担主数据库的压力。
- 数据备份:从数据库作为主数据库的备份,确保数据的安全性。
- 高可用性:主从复制可以用于故障转移,在主数据库发生故障时,从数据库可以提升为主数据库。
2.0 性能优化 (Performance Optimization)
简答回答:
- MySQL 性能优化主要包括查询优化、索引优化和服务器配置优化等几个方面,目的是提高查询效率、减少资源消耗和提升系统响应速度。
常见优化方法:
- 查询优化:
- 使用EXPLAIN分析查询执行计划,找出查询瓶颈。
- 避免 SELECT *,只选择需要的字段,减少不必要的数据加载。
- 优化查询条件,例如将较慢的 LIKE 操作替换为精确的匹配。
- 分解复杂查询,将一个复杂的查询拆解成多个简单的查询。
- 索引优化:
- 为常用的查询条件(如 WHERE、JOIN)添加适当的索引,提高查询速度。
- 避免过多索引,虽然索引能提高查询效率,但也会增加写入操作的开销。
- 缓存优化:
- 使用Query Cache(如果启用),缓存常见的查询结果,减少数据库查询的压力。
- 使用外部缓存系统(如 Redis、Memcached)来缓存热点数据,进一步减少数据库的负载。
- 数据库配置优化:
- 根据硬件资源调整 MySQL 的配置参数(如
innodb_buffer_pool_size,query_cache_size),使数据库能够高效利用系统资源。 - 调整连接数、线程数等参数,以保证数据库能在高并发下稳定运行。
- 根据硬件资源调整 MySQL 的配置参数(如
举个例子:
- 如果一个查询涉及大量数据的 JOIN 操作,可能会导致性能瓶颈。在这种情况下,可以通过优化索引,或者将查询分解成更小的部分来减少数据库的负载。
面试注意:
- 主从复制的重点是数据的同步和负载均衡,而性能优化的重点是减少查询时间、减少资源消耗和提高系统稳定性。
- 在提到优化时,可以举出具体的例子,例如通过使用索引提高了查询性能,或者通过主从复制实现了负载均衡等。