mysql事务变量_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;
分享到:
2016-03-23 18:49
瀏覽 961
分類:數據庫
評論
總結
以上是生活随笔為你收集整理的mysql事务变量_mysql学习四之事务、变量、触发器、函数、存储过程的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: mysql8.0.17压缩包安装教程_超
- 下一篇: mysql online ddl和pt_