六、MySQL事務與存儲過程

JDBC事務控制

事務概述:指邏輯上的一組操作,組成這組操作的各個單元,要麼全成功,要麼全部不成功。

舉例說明:銀行中要將A賬戶中轉100元到B賬戶,這兩步操作必須都成功或都不成功

update account set money = money-100 where name='A';
update account set money = money+100 where name='B';

控制事務語法格式

start transaction;//開啓事務,在這條語句之後的sql將處在同一事務中,並不會立即影響到數據庫
...
...
commit;--提交事務,讓這個數據中的sql對數據庫的影響立即發生
rollback;--取消事務,對數據庫不會產生任何影響

事務的四大特性

  1. 原子性:事務是一組不可分割的單位,要麼同時成功要麼都失敗
  2. 一致性:事務的前後的數據完整性保持一致
  3. 隔離性:多個用戶併發訪問時,一個用戶的事務不被其他用戶干擾
  4. 持久性:一個事務一旦被提交,它對數據庫中的數據的改變是永久性的。不能再回滾

事務的隔離級別

四大隔離級別

髒讀:一個事務讀到另一個事務未提交的數據。
不可重複讀:事務T1讀取某一數據,事務T2讀取並修改了該數據,T1爲了對讀取值進行檢驗而再次讀取該數據,便得到了不同的結果。
虛讀:T1讀取滿足某種搜索條件的一些行,然後T2插入了符合T1的搜索條件的一個新行。如果T1重新執行產生原來那些行的查詢,就會得到不同的行。

  1. read uncommitted:不作任何隔離,具有髒讀,不可重複讀,虛讀問題
  2. read committed:可以防止髒讀,不能防止不可重複讀,虛讀問題
  3. Repeatable read:可以防止髒讀,不可重複讀,不能夠防止虛讀問題(MySQL默認值)
  4. Serializable:數據庫運行在串行化模式下,所有問題都防止,但是性能非常低

設置隔離級別

set [session/global] transaction isolation level ...;-- 修改當前隔離級別
select @@tx_isolation;-- 查詢當前數據庫的隔離級別

存儲過程的創建

概述:一條或者多條SQL語句的集合,當數據庫進行一系列複雜操作時,存儲過程可以將這些複雜操作封裝成一個代碼塊,以便重複使用。

如何創建存儲過程

CREATE PROCEDURE sp_name([proc_parameter]) [characteristics...] routine_body;

--proc_parameter爲指定存儲過程的參數列表,形式如下
[IN/OUT/INOUT]param_name type
--IN表示輸入參數,OUT表示輸出參數,INOUT表示既可以輸入也可以輸出
--param_name表示參數名稱,type表示參數類型
--例一:創建一個查看student表的存儲過程
select * from student;

--將結束符分號改爲雙斜槓
DELIMITER //
create procedure Proc()
BEGIN
    select *from student;
END //
DELIMITER ;

使用:
call Proc();

變量的使用

--定義變量:DECLARE關鍵字,變量的聲明一定在存儲過程中,作用範圍是當前存儲過程。
DECLARE var_name[,varname]...date_type[DEFAULT value];

--DEFAULT value爲默認值
--修改變量值
方法1SET var_name = expr[,var_name=expr]...;
方法2SELECT col_name[...] INTO var_name[...] table_expr;
--例一:定義一個名稱爲myvariable變量,類型爲INT類型,默認值爲100
DECLARE myvariable INT DEFAULT 100;

--例二:修改上例中的變量的值
SET myvariable = 200;

--例三:定義變量,保存學生表中查詢到的班級和性別信息
DELIMITER //
create procedure proc3()
BEGIN 
    DECLARE s_grade float; 
    DECLARE s_gender char(2); 
    select grade.gender into s_grade,s_gender from student where id=3;
END//
DELIMITER ;

定義條件和處理程序

--定義條件使用DECLARE語句,語法格式如下
DELCARE condition_name CONDITION FOR [condition_type];

--condition_type的兩種形式:
[condition_type]:
    SQLSTATE[VALUE] sqlstate_value或者mysql_error_code
 
sqlstate_value和mysql_error_code都可以表示錯誤MySQL的錯誤

--定義處理程序
DECLARE handler_type HANDLER FOR condition_value[...] sq_statement;
handler_type:CONTINUE(遇到錯誤繼續運行)
或者EXIT(遇到錯誤退出)
或者UNDO(遇到錯誤撤回操作,MySQL不支持)
 
condition_value:
SQLSTATE[VALUE]
或者condition_name
或者SQLWARNING(以01開頭的SQLSTATE的錯誤)
或者NOT FOUND(以02開頭的SQLSTATE的錯誤)
或者SQLEXCEPTION(匹配所有沒有被前兩個捕獲的錯誤代碼)
或者mysql_error_code
--例一:定義ERROR 1148(42000)錯誤,名稱爲command_not_allowed的條件
declare command_not_allowed condition for SQLSTATE 42000;
或者
declare command_not_allowed condition for 1148;

--例二:定義上例中的錯誤的錯誤程序
declare continue handler for command_not_allowed SET @info='ERROR';

光標(遊標)的使用

--聲明光標
DECLARE cursor_name CURSOR FOR select_statement;
--爲select-statement的查詢結果定義一個光標

--光標的使用
OPEN cursor_name
FETCH cursor_name INTO var_name[,varname]...--這裏的變量要在遊標之前定義好,每次調用均下移一條數據

//關閉遊標
CLOSE cursor_name;

流程控制的使用

  1. IF語句:滿足某種條件,執行相應語句
IF expr_condition THEN statement_list
    [ELSEIF expr_condition THEN statement_list]...
    [ELSE statement_list]
END IF
例一:創建一個存儲過程判斷變量v的值是否是null,輸出對應的提示信息
delimiter //
create procedure proc3()
BEGIN 
    declare v varchar(2); 
    IF v is null then select 'is null'; 
    ELSE select 'not null'; 
    END IF;
END//
delimiter ;
  1. CASE語句
--格式一
CASE case_expr
    WHEN when_value THEN statement_list;
    [WHEN when_value THEN statement_list]...
    [ELSE statement_list]
END CASE;
--格式二
CASE
    WHEN expr_condition THEN statement_list;
    [WHEN expr_condition THEN statement_list;]...
    [ELSE statement_list;]
END CASE;
例一:使用CASE流程控制語句的第一中格式,判斷var值等於1,等於2,或者兩者都不等
delimiter //
create procedure proc4()
BEGIN 
    declare var INT default 1; 
    CASE var WHEN 1 THEN select 'var is 1'; 
    WHEN 2 THEN select 'var is 2'; 
    ELSE select 'var is not 1 or 2'; 
    END CASE;
END//
delimiter ;
  1. LOOP語句:用於重複執行某些語句
[loop_labe1:]LOOP
statement_list;
END LOOP [loop_labe1];
例一:使用LOOP語句進行循環操作
declare id INT default 0;
add_loop LOOPSET id=id+1; 
IF id>=10 THEN LEAVE add_loop; 
END IF;
END LOOP add_loop;
  1. LEAVE語句:跳出循環,即:java中的break
LEAVE lable;
  1. ITERATE語句:重新開始下一輪循環:即:java中的continue
ITERATE lable;
例一:
create procedure doiterate()
BEGIN
    declare p1 INT default 0;
    my_loop:LOOP set p1=p1+1; 
    IF p1<10 THEN ITERATE my_loop; 
    ELSEIF p1>20 THEN LEAVE my_loop; 
    END IF; 
    select 'p1 is between 10 and 20';
    END LOOP my_loop;
END
  1. REPEAT語句:創建一個帶有判斷條件的循環語句
[repeat_lable] REPEAT
statement_list;
UNTIL expr_condition;
END REPEAT[repeat_lable]
--expr_condition爲真則退出循環
例一:
declare id INT default 0;
REPEAT set id = id + 1; 
until id>=10;
END REPEAT;
  1. WHILE語句
[while_lable:] WHILE expr_condition DO
    Statement_list;
END WHILE [while_lable];
例一:
declare i INT default 0;
WHILE i<10 DO set i=i+1;
END WHILE;

存儲過程的使用

調用存儲過程:CALL關鍵字

CALL sp_name([parameter[,...]]);
例一:創建存儲過程
deltimiter //
create procedure CountProc1(IN s_gender varchar(50), OUT num INT);
BEGIN 
    select count(*) INTO num from student WHERE gender=s_gender;
END //
delimiter ;

例二:使用存儲過程
CALL CountProc1('女',@num);

查看存儲過程

  1. SHOW STATUS語句查看存儲過程的狀態
SHOW {PROCEDURE或者FUNCTION} STATUS [LIKE 'pattern'];
例一:
--查看當前所有的存儲過程
show procedure status;

--查看以2結尾的存儲過程
show procedure status like '%2';
  1. SHOW CREATE語句,查看存儲過程的狀態
SHOW CREATE{PROCEDURE或者FUNCTION} sp_name;
--例一:
show create procedure proc4;
  1. 從表information_schema.Routines中查看存儲過程信息
select * from information_schema.Routines;

修改存儲過程

ALTER {PROCEDURE或者FUNCTION} sp_name[characteristic...];

characteristic:
    CONTAINS SQL 表示子程序包含SQL語句,但不包含或寫數據的語句
    NO SQL 表示子程序中不包含SQL語句
    READS SQL DATA 表示子程序中包含寫數據的語句
    SQL SWCURITY{DEFINER或者INVOKER} 指明誰有權限來執行
    DEFINER 表示只有定義者自己才能執行
    INVOKER 表示調用者可以執行
    COMMENT string 表示註釋信息
注意:MySQL中只能修改存儲過程的特性,不能修改代碼。
例一:修改存儲過程countproc1的定義,將讀寫權限改爲MODIFIES SQL DATA,並指明調用中可執行

alter procedure countproc1 MODIFIES SQL DATASQL SECURLTY INVOKER;

刪除存儲過程

DROP {PROCEDURE或者FUNCTION} [IF EXISTS] sp_name;
例一:刪除存儲過程CountProc1
drop procedure CountProc1;
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章