資料庫—事務與儲存過程
***事務管理
事務中的語句要麼都執行,要麼都不執行
*開啟事務 start transaction
*提交事務 commit (之前的mysql都是直接提交的,而在事務中則需要使用commit語句進行提交)
*如果不想提交事務,取消事務(回滾) rollback (只針對未提交的事物,已提交的事務是不能進行回滾的)
事務有很嚴格的定義,它必須同時滿足4個特性(ACID標準):原子性、一致性、隔離性、永續性
**事務的隔離級別
資料庫是多執行緒併發訪問的,很容易出現多個執行緒併發使用的情況
可能產生的情況:
髒讀:一個事務讀取了另一個事務未提交的資料
不可重複讀:事務中兩次查詢的結果不一致,因為查詢過程中其他事務做了更新的操作
幻讀,又稱虛讀,指一個事務內兩次查詢中資料條數不同,因為查詢過程中其他事務做了插入操作
* 為事務設定隔離級別的語法:set session transaction isolation level 隔離級別
session 表示當前會話,transaction 表示事務 ,isolation 表示隔離 , level 表示級別
*查詢當前會話的隔離級別:select @@transaction_isolation
讀未提交(read uncommitted):事務隔離中的最低級別,該級別下會出現髒讀,這是相當危險的。開發過程中很少使用
讀提交(read commited):大多數資料庫管理系統預設的隔離級別。該級別下只能讀取其他事務已經提交的內容,可以避免髒讀,但不能避免重複讀和幻讀
可重複讀(repeatable read):mysql預設的事務隔離級別。可以避免髒讀和不可重複讀。通過版本更新也可避免幻讀
可序列化(serializable):事務的最高級別。強制事務進行排序,以此解決髒讀等問題,這個級別非常耗時,並且可能導致大量的超時現象和鎖競爭,實際很少使用
*建立儲存過程:create procedure sp_name ([proc_parameter]) [characteristics···]routine_body
(create procedure 是建立儲存過程的關鍵字,sp_name儲存過程名稱,
proc_parameter指定儲存過程引數列表,該引數列表的形式:[in|out|inout])param_name type
in 表示輸入引數,out 表示輸出引數,inout 表示即可輸入又可輸出;param_name 表示引數名稱;type 表示引數型別,可以是MySQL庫中的任意型別
delimiter // 將MySQL的結束符設定為//,以end // 結束儲存過程;儲存過程定義完畢後再使用 delimiter ; 恢復預設結束符,delimiter 也可指定其他符號作為結束符。
注:delimiter 與要設定的結束符之間一定要有一個空格,否則設定無效
**變數的使用
*定義變數: declare var_name[,varname]···data_type[default value];
var_name 為區域性變數的名稱,default value 子句給變數提供一個預設值。該值除了可以被宣告為一個常數外,還可以被指定為一個表示式。如果沒有default子句,變數的初始值為null。
例:定義一個名稱為myvariable的變數,型別為int型別,預設值為100
declare myvariable int default 100;
*定義變數之後可以給變數賦值:set var_name = expr[,var_name=expr]···;
例:宣告變數var1、var2、var3,資料型別為int:declare var1,var2,var3 int;
set var1=10,var2=20;
set var3=var2+var1;
*select ··· into 為一個或多個變數賦值:select col_name [···] into var_name[···] table_expr;
col_name 表示欄位名稱;var_name 表示定義的變數名稱;table_expr 表示查詢條件表示式,包括表名稱和where子句
例:宣告變數s_grade 和 s_gender :declare s_grade float;
declare s_gender char(2);
select grade,gender into s_grade,s_gender
from student where name = 'rose';
*定義條件,使用declare語句:declare condition_name condition for [condition_type];
// condition_type 的兩種形式;
[condition_type] :
sqlstate [value] sqlstate_value|mysql_error_code
condition_name表示所定義的條件的名稱;condition_type表示條件的型別;sqlstate_value和mysql_error_code為數值型別的錯誤程式碼。如:ERROR1142(42000) ,sqlstate_value的值是42000,mysql_error_code的值是1142
*定義處理程式:declare handler_type handler for condition_value[,···] sp_statement
handler_type:
continue|exit|undo
condition_value:
|condition_name
|sqlwarning
|not found
|sqlexception
|mysql_error_code
注:handler_type為錯誤處理方式,引數取三個值:continue、exit、undo。continue 表示遇到錯誤不處理,繼續執行;exit 表示遇到錯誤馬上退出;undo 表示遇到錯誤後撤回之前的操作,MySQL暫時不支援這種操作。sp_statement引數為程式語句段,表示在遇到定義的錯誤時,需要執行的儲存過程;condition_value 表示錯誤型別
*游標的使用:(在編寫儲存過程中,查詢語句可能會返回多條記錄,如果資料量非常大,則需要使用游標來逐條讀取查詢結果集中的記錄。游標是一種用於輕鬆處理多行資料的機制。)
#游標的宣告(游標必須宣告在宣告變數、條件之後,宣告處理程式之前): declare cursor_name cursor for select_statement;
cursor_name 表示游標的名稱,select_statement 表示select語句的內容,返回一個用於建立游標的結果集
例:宣告一個名為 cursor_name 的游標:declare cursor_name cursor for select s_name,s_gender from student;
#開啟游標:open cursor_name
#游標的使用:(使用游標之前首先要開啟游標): fetch cursor_name into var_name[,var_name]···
cursor_name表示引數的名稱;var_name表示將游標中的select語句查詢出來的資訊存入該引數中,需要注意的是,var_name 必須在宣告游標之前就定義好。
例:使用名稱為cursor_student的游標,將查詢出來的資訊存入s_name和s_gender中: sursor_student into s_name,s_gender;
#游標的關閉:close cursor_name; (如果沒有明確的關閉游標,它會在其宣告的複合語句的末尾被關閉)
**流程控制的使用
MySQL中流量控制語句包括:if語句、case語句、loop語句、while語句、leave語句、iterate語句、repeat語句和while語句。每個流程中可能包含一個單獨語句,也可能使用begin···end構造的複合語句,可以巢狀
# if語句:如果滿足某種條件,就根據判斷的結果為true或false執行相應的語句
if expr_condition then statement_list
[elseif expr_condition then statement_list]
[else statement_list]
end if
:expr_condition 表示判斷條件,statement_list表示SQL語句列表,它可以包括一個或多個語句,如果expr_condition求值為true,相應的SQL語句就會被執行;如果沒有expr_condition匹配,則else子句裡的語句列表被執行
# case語句:是另一個進行條件判斷的語句,該語句有兩種格式,
第一種:
case case_expr
when when_value then statement_list
[when when_value then statement_list] ···
[else ststement_list]
end case
:case_expr 表示條件判斷的表示式,決定了哪一個when子句會被執行;when_value 表示表示式可能的值,如果某個when_value表示式與case_expr表示式結果相同,則執行對應then關鍵字後的statement_list中的語句,statement_list 表示不同when_value值的執行語句。
第二種:
case
when expr_condition then statement_list
[when expr_condition then statement_list]
[else statement_list]
end case;
注:儲存過程裡的case語句不能有else null子句,並且用end case 替代end來終止
# loop語句:用來重複執行某些語句,與if和case語句相比,loop只是建立一個迴圈操作的過程,並不進行條件判斷。loop內的語句一直重複執行直到跳出迴圈語句。
[loop_label:] loop
statement_list
end loop [loop_label]
loop_label 表示loop語句的標註名稱,該引數可以省略。statement_list 表示需要迴圈執行的語句
例:declare id int default 0;
add_loop:loop
set id = id+1;
if id>=10 then leave add_loop;
end if;
end loop add_loop;
# leave 語句:當不滿足迴圈條件時,需要使用leave語句退出迴圈,leave語句用於退出任何被標註的流程控制構造
leave label;
label 表示迴圈的標誌。通常情況下,leave語句與begin···end、迴圈語句一起使用
# iterate 語句:iterate的意思是再迴圈,iterate語句用於將執行順序轉到語句段的開頭處
iterate lable
lable 表示迴圈的標誌,注:iterate語句只可以出現在loop、repeat和while語句內
# repeat語句:用於建立一個帶有條件判斷的迴圈過程,每次語句執行完畢之後,會對條件表示式進行判斷,如果表示式為真,則迴圈結束;否則重複執行迴圈中的語句
[repeat_lable:] repeat
statement_list
until expr_condition
end repeat [repeat_lable]
repeat_lable為repeat語句的標註名稱,該引數是可選的,repeat語句內的語句或語句群被重複,直到 expr_condition 為真
# while語句:建立一個帶條件判斷的迴圈過程,與repeat 不同的是,while在語句執行時,先對指定表示式進行判斷,如果為真,則執行迴圈內的語句,否則退出迴圈
[while_lable:] while expr_condition do
Statement_list
end while [while_lable]
while_lable 為while語句的標註名稱;expr_condition 為進行判斷的表示式,如果表示式結果為真,while語句內的語句或語句群被執行,直至expr_condition為假,退出迴圈
**儲存過程的使用
# 呼叫儲存過程(儲存過程有很多呼叫方法。儲存過程必須使用call語句呼叫,並且儲存過程和資料庫相關,如果要執行其他資料庫中的儲存過程,需要指定資料庫名稱):call sp_name([parameter[,···]])
sp_name 為儲存過程的名稱,parameter 為儲存過程的引數
# 檢視儲存過程:
1、show status 語句檢視儲存過程的狀態:show {procedure|function} status [like'pattern']
procedure和function分別表示檢視儲存過程和函式,like表示匹配的名稱
2、show create 語句檢視儲存過程的狀態:show create {procedure|function} sp_name
類似於show create table,它返回一個可用來重新建立已命名子程式的確切字串
3、從information_schema.Routines表中檢視儲存過程的資訊
select * from information_schema.Routines
where routine_name='CountProcl' and routine_type='procedure'\G;
注:在information_schema資料庫下的Routines表中,儲存所有儲存過程的定義。使用select語句查詢Routine 表中的儲存過程的定義時,一定要使用ROUTINE_NAME欄位指定儲存過程的名稱,否則將查詢出所有儲存過程的定義。
# 修改儲存過程:alter {procedure|function} sp_name [characteristic···]
sp_name 表示儲存過程或函式的名稱;characteristic表示要修改儲存過程的哪個部分,characteristic有8部分
# 刪除儲存過程:drop {procedure|function}[if exists] sp_name
sp_name 為要移除的儲存過程的名稱。if exists 表示如果程式不存在,它可以避免產生錯誤,產生一個警告。該警告可以使用show warnings 進行查詢
例:刪除儲存過程CountProc1:drop procedure CountProc1;