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;--取消事務,對數據庫不會產生任何影響
事務的四大特性
- 原子性:事務是一組不可分割的單位,要麼同時成功要麼都失敗
- 一致性:事務的前後的數據完整性保持一致
- 隔離性:多個用戶併發訪問時,一個用戶的事務不被其他用戶干擾
- 持久性:一個事務一旦被提交,它對數據庫中的數據的改變是永久性的。不能再回滾
事務的隔離級別
四大隔離級別
髒讀:一個事務讀到另一個事務未提交的數據。
不可重複讀:事務T1讀取某一數據,事務T2讀取並修改了該數據,T1爲了對讀取值進行檢驗而再次讀取該數據,便得到了不同的結果。
虛讀:T1讀取滿足某種搜索條件的一些行,然後T2插入了符合T1的搜索條件的一個新行。如果T1重新執行產生原來那些行的查詢,就會得到不同的行。
- read uncommitted:不作任何隔離,具有髒讀,不可重複讀,虛讀問題
- read committed:可以防止髒讀,不能防止不可重複讀,虛讀問題
- Repeatable read:可以防止髒讀,不可重複讀,不能夠防止虛讀問題(MySQL默認值)
- 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爲默認值
--修改變量值
方法1:SET var_name = expr[,var_name=expr]...;
方法2:SELECT 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;
流程控制的使用
- 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 ;
- 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 ;
- 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;
- LEAVE語句:跳出循環,即:java中的break
LEAVE lable;
- 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
- 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;
- 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);
查看存儲過程
- SHOW STATUS語句查看存儲過程的狀態
SHOW {PROCEDURE或者FUNCTION} STATUS [LIKE 'pattern'];
例一:
--查看當前所有的存儲過程
show procedure status;
--查看以2結尾的存儲過程
show procedure status like '%2';
- SHOW CREATE語句,查看存儲過程的狀態
SHOW CREATE{PROCEDURE或者FUNCTION} sp_name;
--例一:
show create procedure proc4;
- 從表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;