视图
SQL语句的执行后产生的结果是一张虚拟表,我们可以对该表做其他操作,如果这张虚拟表需要频繁使用,那我们就可以将这张虚拟表保存起来,保存起来的就被称为'视图'
create view 视图名 as SQL语句;
create view teacher2course as
select * from teacher inner jojin course on teacher.tid = course.teacher_id;
'''
在硬盘中,视图只有表结构文件,没有表数据文件
视图通常是用于查询,尽量不要修改视图中的数据
当对通过视图看到的数据进行修改时,相应的基本表的数据也要发生变化
若基本表的数据发生变化,则这种变化也可以自动地反映到视图中
'''
触发器
1. 触发器是保证数据完整性的一种方法,它的执行是由事件来触发的,对表的增、改、删都会自动触发该功能(增前、增后、改前、改后、删前、删后)
defore/after insert/update/delete on 表名 for each row
begin
SQL语句
end
2. 触发器内部需要用到分号,但分号又是SQL语句默认的结束符,所以为了能完整的使用触发器,需要临时修改SQL语句默认的结束符
delimiter $$
需要使用分号的SQL语句
delimiter :
3. 例子
create table cmd (id int primary key auto_increment,
user char(32 ),priv char(10 ),cmd char(64 ),
sub_time datetime,
success enum ('yes' ,'no' ));
create table cmd (id int primary key auto_increment,
err_cmd char(64 ),
err_time datetime);
delimiter $$
sreate trigger tri_after_insert_cmd after insert on cmd for each row
begin
if new.success = 'no' then
insert into errlog(err_cmd,err_time) values(new.cmd,new.sub_time);
end if ;
end $$
delimiter ;
'''
sreate trigger命令定义触发器,即修改特定表中的数据时要执行的代码块
show triggers;
'''
insert into cmd (user,priv,cmd,sub_time,success)
values('barry' ,'0755' ,'1s -1 /etc' ,now(),'yes' ),
('barry' ,'0755' ,'cat /etc/passwd' ,now(),'no' ),
('harry' ,'0755' ,'useradd xxx' ,now(),'no' ),
('harry' ,'0755' ,'ps aux' ,now(),'yes' );
select * from errlog;
drop trigger tri_after_insert_cmd;
事务
1. 事务的概念
在关系数据库中,一个事务可以是一条SQL语句,一组SQL语句或整个程序
2. 事务的四大特征(ACID)
2.1 A:原子性
一个事务是一个不可分割的工作单位,事务中的操作要么都做,要么都不做
2.2 C:一致性
事务必须是数据库从一个一致性状态变到另一个一致性状态,因此当数据库只包含成功事务提交的结果时,就说数据库处于一致性状态,一致性与原子性是密切相关的
2.3 I:隔离性
一个事务的执行不能被其他事务干扰
2.4 D:持久性
一个事务一旦被提交,它对数据库中数据的改变就应该是永久的,之后的其他操作不应该对其有任何影响
3. 使用
create table user(id int primary key auto_increment,
name char(32 ),balance int );
insert into user(name,balance) values
('barry' ,1000 ),
('harry' ,1000 ),
('tom' ,1000 );
start transaction
update user set balance=900 where name='barry' ;
update user set balance=1010 where name='harry' ;
update user set balance=1090 where name='tom' ;
rollback;
commit;
'开启事务检测操作是否完整,不完整则回滚到上一状态,完整则执行commit操作'
try :
update user set balance=900 where name='barry' ;
update user set balance=1010 where name='harry' ;
update user set balance=1090 where name='tom' ;
except 异常:
rollback;
else :
commit;
4. 扩展知识
4.1 MySQL提供两种事务型存储引擎InnoDB和NDB、cluster及第三方XtraDB、PBXT
4.2 事务处理中有几个关键词汇会反复出现
事务(transaction)
回退(rollback)
提交(commit)
保留点(savepoint)
4.3 为了支持回退部分事务处理,必须在事务处理块中适合的位置放置占位符,这样如果需要回退就可以回退到某个占位符(保留点)
创建占位符可以使用savepoint
savepoint.sp01;
回退到占位符位置
rollback to sp01;
5. 在SQL标准中定义了四种隔离级别,每一种级别都规定了一个事务中所做的修改
InnoDB支持所有隔离级别
set transaction isolation level 级别
5.1 read uncommitted(未提交读)
事务中的修改即使没有提交,对其他事务也都是可见的,事务可以读取未提交的数据,这一现象也称为'脏读'
5.2 read uncommitted(提交读)
大多数数据库系统默认的隔离级别
一个事务从开始到提交之前所做的任何修改对其他事务都是不可见的,这种级别也叫'不可重复读'
5.3 repeatable read(可重复读)
可以解决'脏读' 问题,但无法解决'幻读'
所谓幻读指的是当某个事务在读取某个范围内的记录时另外一个事务又在该范围内插入了新的记录,当之前的事务再次读取该范围的记录会产生幻行,InnoDB和XtraDB通过多版本并发控制(MVCC)及间隙锁策略可以解决该问题
5.4 serializable(可串行读)
6. 事务日志
6.1 事务日志可以帮助提高事务的效率
6.2 存储引擎在修改表的数据时,只需要修改其内存拷贝再把该修改记录到持久在硬盘上的事务日志中,而不用每次都将修改的数据本身持久到磁盘
6.3 事务日志采用的是追加方式,因此写日志操作是磁盘上一小块区域内的顺序IO,而不像随机IO需要次哦按的多个地方移动磁头,所以采用事务日志的方式相对来说要快的多
6.4 事务日志持久之后,内存中被修改的数据再后台可以慢慢刷回磁盘,目前大多数存储引擎都是这样实现的,通常称之为'预写式日志' 修改数据需要写两次磁盘
mvcc多版本并发控制
1. MVCC 是一种并发控制的方法,一般在数据库管理系统中,实现对数据库的并发访问
2. MVCC只能在read committed(提交读)、repeatable read(可重复读)两种隔离级别下工作,其他两个不兼容,read uncommitted总是读取最新,serializable所有的行都加锁
3. InnoDB的MVCC通过在每行记录后面保存两个隐藏的列来实现MVCC
一个列保存了行的创建时间
一个列保存了行的过期时间或删除时间
每开始一个新的事务版号都会自动递增,事务开始时刻的系统版本号会作为事务的版本号,用来和查询到每行记录版本号进行比较
4. 例如
4.1 刚插入第一条数据的时候,我们默认事务id 为1 ,实际是这样存储的
username create_version delete_version
jason 1
我们在content列插入了kobe这条数据,在create_version这列存储了1 ,1 是这次插入操作的事务id
4.2 在将jason修改为barry01,实际存储是这样的
username create_version delete_version
jason 1 2
jason01 2
update的时候,会先将之前的数据delete_version标记为当前新的事务id ,也就是2 ,然后将新数据写入,将新数据的create_version标记为新的事务id
4.3 删除数据的时候,实际存储是这样的
username create_version delete_version
jason01 2 3
'''
由此当我们查询一条记录的时候,只有满足以下两个条件的记录才会被显示出来:
1.当前事务id要大于或者等于当前行的create_version值,这表示在事务开始前这行数据已经存在了
2.当前事务id要小于delete_version值,这表示在事务开始之后这行记录才被删除
'''
存储过程
1. 类似python中的自定义函数
delimiter 临时结束符
create procedure 名字(参数,参数)
begin
SQL语句
end 临时结束符
delimiter $$
create procedure p1(in m int ,
in n int ,out res int )
begin
select tname from teacher where tid > m and tid < n;
set res=0 ;
end $$
delimiter ;
set @res=10 ; 定义
select @res; 查看
call p1(1 ,5 ,@res) 调用
select @res 查看
'''
1.查看存储过程具体信息
show create procedure pro1;
2.查看所有存储过程
show procedure status;
3.删除存储过程
drop procedure pro1;
'''
内置函数
'可以通过help 函数名 查看帮助信息'
1. 移除指定字符
Trim、LTrim、RTrim
1.1 Trim例
select trim(' bar ' );
select trim(leading'x' from 'xxbarxx' );
select trim(trailing'x' from 'xxbarxx' );
1.2 LTrim例
select ltrim(' bar' );
1.3 RTrim例
select rtrim('bar ' );
2. 大小写转换
Lower、Upper
select lower('BAR' );
select upper('bar' );
3. 获取左右起始指定个数字符
Left、Right
2.1 Left例
select left('abcdefg' ,3 );
2.2 Right例
select right('abcdefg' ,3 );
4. 返回读音相似值(对英文效果)
Soundex
'''
eg:客户表中有一个顾客登记的用户名为J.Lee
但如果这是输入错误真名其实叫J.Lie,可以使用soundex匹配发音类似的
where Soundex(name)=Soundex('J.Lie')
'''
5. 日期格式:date_format
'在MySQL中表示时间格式尽量采用2022-11-11形式'
create table blog(id int primary aut_increment,
name char(32 ),sub_time datetime);
insert into blog(name,sub_time) values
('第1篇' ,'2015-03-01 11:31:21' ),
('第2篇' ,'2015-03-11 16:31:21' ),
('第3篇' ,'2016-07-01 10:21:31' ),
('第4篇' ,'2016-07-22 09:23:21' ),
('第5篇' ,'2016-07-23 10:11:11' ),
('第6篇' ,'2016-07-25 11:21:31' ),
('第7篇' ,'2017-03-01 15:33:21' ),
('第8篇' ,'2017-03-01 17:32:21' ),
('第9篇' ,'2017-03-01 18:31:21' );
select date_format(sub_time,'%Y-%m' ),count(id ) from blog group by date_fromat(sub_time,'%Y-%m' );
where Date(sub_time) = '2015-03-01'
hwere Year(sub_time)=2016 and Month(sub_time)=07;
'''
其他日期处理相关函数
adddate 增加一个日期
addtime 增加一个时间
datediff 计算两个日期差值
'''
流程控制
1. if 条件语句
delimiter //
create procedure proc_if ()
begin
declare i int default 0 ;
if i = 1 then
select 1 ;
elseif i = 2 then
select 2 ;
else
select 7 ;
end if ;
end //
delimiter ;
2. while 循环
delimiter //
create procedure proc_while ()
begin
deckare num int ;
set num = 0 ;
while num < 10 do
select
num ;
set num = num + 1 ;
end while
end //
delimiter ;
索引
1. 索引就像是书的目录,它能让你更快的找到自己想要的内容
2. 让获取的数据更有目的性,从而提高数据库检索数据的性能
3. 索引在MySQL中也叫做'键' ,是存储引擎用于快速找到记录的一种数据结构
primary key
unique key
index key
'这三种键在数据查询的时候使用,都可以加快查询的速度'
primary key、unique key除了可以加快数据查询还有额外限制
index key只能加快数据查询,本身没有任何额外限制
4. 理解索引加快数据查询
索引的存在可以加快数据查询,但是会减慢数据的增删
5. 索引相关概念
索引是为了加速对表中数据行的检索而创建的一种分散的存储结构,是针对表而建立的,它是由数据页面以外的索引页面组成的,每个索引页面中的行都会含有逻辑指针,以便加速检索物理数据
索引底层原理
1. 树
一种数据结构,主要用于优化数据查询的操作
2. 二叉树:两个分支
B树(B-树)、B+树、B*树
2.1 B树
除了叶子节点可以有多个分支,其他节点最多只能两个分支,所有节点都可以直接存放完整数据(每个数据块是有固定大小的)
2.2 B+树
只有叶子节点存放真正的数据,其他节点只存放主键值(辅助索引值)
2.3 B*树
在树节点添加了通往其他节点的通道,减少查询次数
慢查询优化
explain SQL语句
'''
慢查询可以在日志中记录运行比较慢的SQL语句,通过慢查询可以找出SQL语句中执行效率低的,进行优化
'''
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?