`

mysql学习四之事务、变量、触发器、函数、存储过程

 
阅读更多
需求:有一张银行账户表,有A用户给B用户转账;A账户先减少,B账户增加,但是A操作完之后断电了。

解决方案:A减少钱,但是不要立即修改数据表;B收到钱之后,同时修改数据表


事务安全

事务:transaction,一系列要发生的连续的操作
事务安全:一种保护连续操作同时满足(实现)的一种机制

事务安全的意义:保证数据操作的完整性


--创建一个账户表
create table my_account(
number char(16) not null unique comment '账户',
name varchar(20) not null,
money decimal(10) default 0.0 comment '账户余额'
)charset utf8;

insert into my_account values('0000000000000001','张三',1000),('0000000000000002','李四',1000);

alter table my_account add id int primary key auto_increment first;

update my_account set money = money - 1000 where id= 1; 


事务操作
事务操作分为两种:自动事务(默认的),手动事务 

手动事务:操作流程
1、开启事务:告诉系统以下所有的操作(写)不要直接写入到数据表,先存到事务日志
--开启事务
start transaction;

2、进行事务操作:一系列操作
	a)李四账户减少
update my_account set money = money - 1000 where id = 2; 
	b)张三账户增加
update my_account set money = money + 1000 where id = 1; 

3、关闭事务:选择性的将日志文件中操作的结果保存到数据表(同步)或者说
直接清空事务日志(原来操作全部清空)
	a)提交事务:同步数据表(操作成功)commit;
	b)回滚事务;直接清空(操作失败)  rollback;
--提交事务 
commit;


事务原理
开启事务后,后续的所用操作(写);会先写到临时日志文件,
接收SQL语句,执行SQL语句;结果先写入到临时日志文件;
查询操作:会从数据表查询,经过临时日志文件结果加工后返回
事务结束:commint或rollback,清空临时日志文件,commit会同步到数据表,
rollback是直接清空
如果断开连接,临时事务文件会自动清空。


回滚点
在某个成功的操作完成之后,后续的操作有可能成功有可能失败,但是不管
成功还是失败,前面操作都已经成功;可以在当前成功的位置,设置一个点;
可以供后续失败操作返回该位置,而不是返回所有操作,这个点称为回滚点。

设置回滚点语法:savepoint 回滚点名字

回到回滚点语法:rollback to 回滚点名字 

--回滚点操作

--开启事务 
start transaction;
--事务处理1:张三加钱
update my_account set money=money+10000 where id = 1;
--查看结果
select * from my_account;
--设置回滚点 
savepoint sp1;
--银行扣税
update my_account set money=money-10000*0.05 where id=2; --错误
--查看结果
select * from my_account;
--回滚到回滚点
rollback to sp1;
--查看结果
select * from my_account;
--继续操作
update my_account set money=money-10000*0.05 where id=1; 
--查看结果
select * from my_account;
--提交事务
commit;


事务特性:四大特性
	A:原子性,事务整个操作是一个整体,不可分割,要么全部成功,要么全部失败
	C:一致性,事务操作的前后,数据表的数据没有变化
	I:隔离性,事务操作是相到隔离不受影响的
	D:持久性,数据一旦提交,不可改变,永久的改变数据表数据
	
锁机制:innodb默认是行锁,但是如果在事务操作的过程中,没有使用到索引,
那么系统会自动全表检索数据,自动升级为表锁。
	行锁:只有当前行被锁住,别的用户不能操作
	表锁:整张表被锁住,别的用户都不能操作。



变量
变量分为系统变量和自定义变量

系统变量:系统自定义好的变量,系统变量是用来控制服务器的表现的,如
autocommit,auto_increment_increment等

查看系统变量
show variables ; --查看所有系统变量
	
查看具体变量值:任何一个有数据返回的内容都是由select查看
select @@变量名;

--查看变量值
select @@version,@@autocommit,@@auto_increment_offset;

修改系统变量
分为两种方式:会话级别和全局级别和全局级别

会话级别:临时修改

--修改会话级别变量 ,当前客户端当次连接有效
set 变量名 = 值 ;  set @@变量名 = 值;
set autocommit = 0 ;

全局级别:一次修改,永久生效(对所有客户端生效)
set global 变量名 = 值;


自定义变量
系统为了区分系统变量,规定用户自定义变量必须使用一个@符号
set @变量名=值;

set @name = '张三';

select @name;

mysql定义的一个赋值符号:=

set @age := 19;

select @age;


mysql允许从数据表中获取数据,然后赋值给变量:两种方式

1、边赋值,边查看结果(只能用:=,=号会解析为比较)
select @变量名 := 字段名 from 数据源;  --从字段中取值赋值给变量名

--从表中获取数据赋值给变量
select @name := name from my_student;

2、只有赋值不看结果,要求很严格:数据记录只能有一条记录
select 字段表 from 数据源 into @变量名
select name,age from my_student where id=2 into @name,@age;

所有自定义的变量都是会话级别:当前客户端当次连接有效
所有自定义变量不区分数据库(用户级别)


需求:有两张,一张订单表,一张商品表,每生成一个订单,意味着商品的库存要
减少

触发器
事先为某张表绑定好一段代码,当表中的某些内容发生改变的时候(增删改)系统
会自动触发代码执行。

事件类型,触发时间,触发对象
	事件类型:增删改,三种类型 insert delete update 
	触发时间:前后,两种 before after
	触发对象:表中的每一条记录(行)

一张表中只能拥有一种触发时间的一种类型的触发器;最多一张表能有6个触发器


创建触发器
在mysql高级结构中:没有大括号,都是用对应的字符符号代替

基本语法
--临时修改语句结束符
delimiter 自定义符号:后续代码中只有碰到自定义符号才结束

create trigger 触发器名字 触发时间 事件类型 on 表名 for each row 
begin   --代表左大括号;开始
	...里面就是触发器的内容:每行内容都必须使用语句结束符,分号
end     --代表右带括号:结束
--语句结束符号
自定义符号 

--将临时修改修正过来
delimiter 


--创建表
create table my_goods(
	id int primary key auto_increment,
	name varchar(20) not null,
	price decimal(10,2) default 1,
	inv int comment '库存'
)charset utf8;

insert into my_goods values(null,'iphone6s',5288,100),(null,'s6',5300,100);

create table my_order(
	id int primary key auto_increment,
	g_id int not null comment '商品ID',
	g_number int comment  '商品数量'
)charset utf8;


--触发器:订单生成一个,商品库存减少
--临时修改语句结束符
delimiter $$

create trigger after_order after insert on my_order for each row
begin
	update my_goods set inv = inv - 1 where id = 2;
end 
$$
delimiter  ;


查看触发器

查看所有触发器或者模糊匹配
show triggers\G; 

--查看触发器创建语句
show create trigger 触发器名字;

show create trigger after_order\G


所有触发器都会存到一个系统表中information_schema.triggers 

select * from information_schema.triggers


使用触发器
不需要手动调用,而是当某种情况发生时,会自动触发

--订单插入记录会自动触发
--触发器工作了,订单生成之后,对应商品数量减少了
--当前商品减少的,不是订单中产生的商品;而是固定的商品(不合理)
--插入订单
insert into my_order values(null,1,2);

修改触发器&删除触发器

触发器不能修改,只能先删除后新增

drop trigger 触发器名字;
--删除触发器
drop trigger after_order;


触发器记录
不管触发器是否触发了,只要当前某种操作准备执行,系统就会将当前要操作的记录的当前状态
和即将执行之后新的状态给分别保留下来,供触发器使用:其中,要操作的当前状态保存到old中,
操作之后的可能形态保存给new

old代表的是旧记录,new代表的是新记录
	删除的时候没有new,插入的时候没有old
old和new代表记录本身,任何一条记录除了数据,还有字段名字
使用方式old.字段名/ new.字段名(new代表假设发生之后的结果)


delimiter $$
create trigger after_order after insert on my_order for each row
begin
	update my_goods set inv = inv - new.g_number where id = new.g_id;
end
$$
delimiter  ;

insert into my_order values(null,1,2);


代码执行结构

三种:顺序结构 、分支结构、循环结构

分支结构
实现准备多个代码块,按照条件选择性的执行某段代码

在mysql中只有if分支

基本语法 
if 条件判断  then
	--满足条件要执行的代码
else
	--不满足条件要执行的代码
end if;

触发器结合If分支,判断商品库存是否足够,不够不能生成商品订单


--库存不够:触发器没有提供一个能够阻止事件发生的能力,暴力报错
delimiter %%
create trigger before_order before insert on my_order for each row
begin
		select inv from my_goods where id = new.g_id into @inv;
		if @inv < new.g_number then 
			insert into XXX values(XXX);
		end if; 
end 
%%
delimiter   ;

--插入订单
insert into my_order values(null,1,1000);


循环结构
某段代码在指定条件重复执行
while循环

while 条件判断 do
	--满足条件要执行的代码
	--变更循环条件
end while;

循环控制:在循环内部进行循环判断和控制
mysql中没有对应的continue和break;但是有替代吕
iterate 迭代,类似continue ,后面的代码不执行,循环重新来过
leave 离开 ,类似break;

使用方式 iterate/leave 循环名字;

--定义循环名字
循环名字:while 条件 do
	--循环体
	--循环控制
		leave/iterate 循环名字
end while;


函数 
将一段代码块封装到一个结构中,在需要执行代码的时候,调用结构执行即可(代码复用)

分为两类:系统函数和自定义函数

系统函数:直接调用即可
任何函数都有返回值,因此函数的调用是通过select调用。

mysql中字符串的基本单位,最常用的是字符
substring  字符串截取,字符为单位substring(str,pos,len);
char_length 字符长度
length		字节长度
instr		判断字符串是否在某个具体字符串中存在
lpad		左填充,将字符串,按照某个指定的填充方式,填充指定长度
insert      字符串替换
strcmp  		字符串比较

--定义两个变量
set @cn = '世界你好';
set @en = 'hello world';

--字符串截取,mysql中字符串下标从1开始,截取单位为字符
select substring(@cn,1,1);
select substring(@en,1,1);

--字符长度
select char_length(@cn),char_length(@en),length(@cn),length(@en); 

--字符串寻找,0代表没有找到
select instr(@cn,'界'),instr(@en,'ll'),instr(@cn,'知道');

--字符串填充
select lpad(@cn,20,'欢迎'),lpad(@en,20,'hello');

--字符串替换
select insert(@en,3,3,'y'),@en;



自定义函数
函数要素:函数名、参数列表(形参和实参),返回值,函数体

创建语法
create function 函数名([形参列表]) returns 数据类型  --规定要返回的数据类型
begin
	--函数体
	--返回值 return类型(指定数据类型)
end

--创建函数
create function display1() returns int
return 100;

--调用函数
select display1();

--查看所有函数
show function status [like ''];

函数属于指定数据,只有在对应数据库下调用 

查看函数的创建
show create function 函数名;

show create function display1;

修改函数&删除函数
函数不能修改,先删除后新增
drop function 函数名;

drop function display1;

函数参数
参数分为两种:定义时的参数叫形参,


--函数:计算1-指定数之间的和
-- 求和:任何变量要修改必须使用set关键字
--@定义的变量是全局变量,没有的是局部变量
delimiter $$
create function display1(int_1 int) returns int
begin
	set @i = 1 ;
	set @res = 0 ;
	while @i <= int_1 do
		set @res =@res+ @i;
		set @i = @i+1;
	end while;
	return @res;
end
$$
delimiter  ;

在函数内部使用@定义的变量在函数外部也可以访问 

作用域
mysql中的作用域与JS中的作用域一样
	全局变量可以在任何地方使用;局部变量只能在函数内部使用
全局变量:使用set关键字定义,使用@符号标志
局部变量:使用declare关键字声明,没有@符号;所有的局部变量的声明


--求和:1-指定数之间的和,要求5的倍数不加
delimiter $$
create function display2(int_1 int) returns int 
begin
	declare i int default 1 ;
	declare res int default 0 ;
	mywhile:while i <= int_1 do
		if i%5=0 then 
			set i = i+1;
			iterate mywhile;
		end if;
		set res = res +i;
		set i = i+1;
	end while;
	return res;
end 
$$
delimiter  ;


存储过程
存储过程是一种没有返回值的函数

创建过程

create procedure 过程名字([参数列表])
begin
	--过程体
end

--创建过程
--假设过程中需要显示数据:使用select
create procedure pro1()
	select * from my_student;
	
查看过程

查看所有过程

show procedure status [like ''];

--查看过程创建语句
show create procedure pro1;

调用过程
过程没有返回值,select是不能访问的
过程有一个专门的调用关键字 call

call pro1();


修改过程&删除过程
过程不能修改,只能先删除后新增
drop procedure 过程名;

drop procedure pro1;

过程参数
函数的参数需要数据类型指定,过程比函数更严格

过重还有自己的类型限定:三种类型
	in:数据只是从外部传入内部使用(值传递);可以是数值,也可以是变量
	out:只允许过程内部使用(不用外部数据),给外部使用的(引用传递,外部的数据会被
		先清空才会进入到内部),只以是变量
	inout:外部可以在内部使用,内部修改也可以给外部使用;典型的引用传递,只能是变量

基本使用:
create procedure 过程名(in 形参名字 数据类型,out 形参名字 数据类型,inout 形参名字 数据类型)


--过程参数
--int_2的值一定是null,Out数据会被先清空
delimiter $$
create procedure pro1(in int_1 int,out int_2 int,inout int_3 int)
begin
	select int_1,int_2,int_3;
end
$$
delimiter  ;

调用 :out 和inout类型的参数必须传入变量而不是数值
set @int_1=1;
set @int_2=2;
set @int_3=3;
select @int_1,@int_2,@int_3;
call pro1(@int_1,@int_2,@int_3);

--局部变量和全局变量没有关系
delimiter $$
create procedure pro2(in int_1 int,out int_2 int,inout int_3 int)
begin
	select int_1,int_2,int_3;
	
	set int_1 = 10 ;
	set int_2 = 100;
	set int_3 = 1000;
	
	select int_1,int_2,int_3;
	select @int_1,@int_2,@int_3;
	
	set @int_1 = 'a';
	set @int_2 = 'b';
	set @int_3 = 'c';
	
	select int_1,int_2,int_3;
	select @int_1,@int_2,@int_3;
end
$$
delimiter  ;
select @int_1,@int_2,@int_3;
最后:在存储过程调用结束之后,系统会将局部变量重新返回给全局变量,只有out,inout;



分享到:
评论

相关推荐

    MySQL数据库函数,触发器,存储过程

    通过深入学习和掌握MySQL的函数、触发器和存储过程,开发者能够更加高效地管理和操作数据库,解决复杂的数据处理问题,提升应用程序的性能。在实际项目中,熟练运用这些特性是数据库设计和优化的关键。通过"mysql...

    MYSQL触发器与存储过程.ppt

    MySQL中的存储过程和触发器是数据库管理中两个重要的高级特性,它们极大地增强了数据库的灵活性和安全性,同时也优化了性能。 **存储过程**是预编译的SQL语句集合,存储在数据库服务器上,可以在需要时被调用执行,...

    MySQL实验报告5(存储过程与函数)(1)(1).pdf

    根据提供的文件内容,本篇实验报告主要围绕MySQL数据库中存储过程和函数的应用,涵盖了创建存储过程、函数、游标以及异常处理等高级特性。下面将详细解析报告中的每个知识点。 1. 创建存储过程 存储过程是一种在...

    mysql函数、存储过程、触发器、游标.doc

    MySQL是世界上最流行的开源关系型数据库管理系统之一,它包含多种功能,如函数、存储过程、触发器和游标,这些功能极大地增强了数据库管理的灵活性和效率。以下是对这些概念的详细解释: 1. **MySQL函数**:MySQL...

    Mysql手册20-存储过程和函数

    MySQL存储过程和函数是数据库编程的重要组成部分,它们提供了在数据库服务器上执行特定任务的能力。本部分详细介绍了存储程序和函数的各个方面,包括它们的创建、语法、权限控制以及与性能优化相关的概念。 首先,...

    如何用Toad调试存储过程、触发器

    调试存储过程和触发器是开发和优化数据库应用程序的关键步骤。以下是使用Toad进行调试的基本步骤和要求: **调试需求:** 1. **SYS.DBMS_DEBUG** 库必须可用。这是Oracle提供的调试API,用于设置断点和检查变量。 2...

    mysql 存储过程中变量的定义与赋值操作

    一、变量的定义 mysql中变量定义用declare来定义...二、mysql存储过程变量赋值 变量的赋值可直接赋值与查询赋值来操作,直接赋值可以用set来操作,可以是常量或表达式如果下 代码如下: set var_name= [,var_name expr]

    MYSQL的存储过程和函数简单写法

    【MySQL存储过程与函数简介】 MySQL的存储过程和函数是数据库管理中强大的工具,它们允许开发者将一组SQL语句组织在一起,形成一个可重用的模块,以执行复杂的业务逻辑。这种概念类似于高级编程语言(如Java)中的...

    mysql存储过程——用于数据库的备份与还原

    这个存储过程可能包含了一些内部函数或变量来处理表名列表,以及可能的配置选项,如是否备份触发器、索引等。为了使用这个存储过程,你需要将其导入到你的MySQL服务器中,然后通过`CALL`语句来执行。 总的来说,...

    2021年MySQL高级教程视频.rar

    17.MySQL高级存储过程语法变量.avi 18.MySQL高级存储过程语法if判断.avi 19.MySQL高级存储过程语法输入参数.avi 20.MySQL高级存储过程语法输出参数.avi 21.MySQL高级存储过程语法case结构.avi 22.MySQL高级存储过程...

    MySQL 5.0 存储过程

    读者在学习过程中会发现,即使开始认为复杂的用例,只要跟随书中的指导,也能很快掌握。对于在不同操作系统上运行存储过程时可能遇到的问题,本书也给出了调试和寻求帮助的方法。 最后,书的结尾部分对MySQL这一...

    实验9 存储过程的创建和使用

    存储过程是一组预先编写的SQL语句,它允许用户像调用函数一样重复执行,提高了数据库操作的效率和安全性。 首先,理解存储过程的分类至关重要。存储过程分为系统存储过程、用户自定义存储过程和扩展存储过程。系统...

    MySQL 5.0存储过程

    同时,存储过程也可以与触发器、游标、变量和函数结合使用,以实现更复杂的数据库操作。 例如,一个简单的存储过程可能是处理用户注册的逻辑,包括检查用户名是否已存在,如果不存在则插入新用户记录。这样的存储...

    MySQL触发器代码

    触发器是一种存储过程,它定义了一组SQL语句,并且被设计成自动响应特定事件(如数据的修改)。触发器通常用于强化复杂的业务规则或者数据完整性约束。它们可以在特定的数据表上执行INSERT、UPDATE或DELETE操作时...

    MySQL数据库:项目以程序方式处理学生信息管理数据表.pptx

    本资源概述了 MySQL 数据库的原理和应用,涵盖了 SQL 编程基础、游标、存储过程和函数、触发器及事务的知识点。 SQL 编程基础 SQL 语言是数据库管理系统的核心语言,掌握 SQL 语言是学习 MySQL 数据库的基础。 SQL...

    MYSQL触发器教程.pdf

    在编写触发器时,你可以使用一系列的编程元素,这些元素与存储过程中的非常相似。比如,你可以使用复合语句(BEGIN/END)、流控制语句(IF, CASE, WHILE, LOOP等)、变量声明(DECLARE)和赋值(SET),甚至处理异常...

    在Mysql存储过程中使用事务实例

    在存储过程的主体中,声明了四个变量:`flag`、`uuidStr`、`currentTime`和`err`。`flag`用于控制循环,`uuidStr`用于存储无连字符的UUID字符串,`currentTime`用于记录当前时间戳,而`err`则作为异常处理的标志,...

Global site tag (gtag.js) - Google Analytics