1. 程式人生 > 資料庫 >資料庫—事務與儲存過程

資料庫—事務與儲存過程

***事務管理

事務中的語句要麼都執行,要麼都不執行

*開啟事務  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;