MySQL遊標和觸發器

1、遊標

定義:是一個存儲在MySQL服務器上的數據庫查詢,是一種被select語句檢索出來的結果集。sql

做用:方便在檢索出來的結果集中前進或後退一行或多行。數據庫

PS遊標主要用於交互式應用;MySQL中的遊標只能用於存儲過程(和函數)。安全

 

1、建立遊標服務器

遊標使用declare語句建立;declare命名遊標,並定義相應的select語句,根據須要帶where和其餘子句;例如:函數

create procedure processorders()
begin
       declare ordernumbers CURSOR
       for
       select order_num from orders;
end;

這個存儲過程當中,declare定義和命名了遊標ordernumbers,存儲過程處理完成後,遊標就消失(侷限於存儲過程內)。oop

 

2、打開和關閉遊標fetch

定義遊標以後,能夠打開它,用open cursor語句來打開,例如:open ordernumbers;spa

在處理open語句時執行查詢,存儲檢索出的數據以供瀏覽和滾動;指針

遊標處理完成時,用close語句關閉,例如:close ordernumbers;code

close釋放遊標使用的全部內部內存和資源,所以在每一個遊標不在須要時都應該關閉。

PS

遊標關閉後,若是沒有從新打開,則不能使用;但若是該遊標被聲明過,則不須要再次聲明,用open打開使用便可。

若是不明確遊標是否關閉,MySQL將會在到達end語句時自動關閉該遊標。

 

3、使用遊標數據

遊標被打開後,使用fetch語句分別訪問它的每一行;fetch指定檢索什麼數據(所需的列),檢索的數據存儲在什麼地方,還向前移動遊標中的內部行指針,使下一條fetch語句檢索下一行(不重複讀取)。

檢索第一行數據,例如:

create procedure processorders()
begin
       --declare local variables
       declare o int;

       --declare the cursor
       declare ordernumbers cursor for select order_num from orders;

       --open the cursor
       open ordernumbers;

       --get order number
       fetch ordernumbers into o;

       --close the cursor
       close ordernumbers;
end;

這條語句中fetch用來檢索當前行的order_num列(自動從第一行開始)到一個名爲o的局部聲明變量中;對檢索出的數據不作任何處理。

循環檢索數據,從第一行到最後一行,以下:

create procedure processorders()  --建立存儲過程
begin
       --declare local variables
       declare done boolean default 0;
       declare 0 int;

       --declare the cursor
       declare ordernumbers cursor
       for select order_num from orders;  --結果集

       --declare continue handler
       declare continue handler for sqlstate '02000' set done=1;  --在這裏,done被設置爲結束時爲真

       --open the cursor
       open ordernumbers;

       --loop through all rows
       repeat

       --get order number
       fetch ordernumbers into o;

       --end of loop
       until done end repeat;

       --close the cursor
       close ordernumbers;
end;

與前一個例子同樣,用fetch檢索當前order_num到聲明的o變量中。區別在於:這個例子中fetch是在repeat內,所以它反覆執行到done爲真(由until done end repeat;規定)。

在語句(declare continue handler for sqlstate '02000' set done=1;)中,定義了CONTINUE HANDLER,它是在條件出現時被執行的代碼。當SQLSTATE '02000'出現時,SET done=1。

SQLSTATE '02000'是一個未找到條件,當REPEAT因爲沒有更多的行供循環而不能繼續時,出現這個條件。done被設置爲真。

PS

用declare語句定義的局部變量必須在定義任意遊標或句柄以前定義,而句柄必須在遊標以後定義。

MySQL還支持循環語句,它可用來重複執行代碼,直到使用leave語句手動退出爲止;一般repeat語句的語法使它更適合於對遊標進行循環。

 

4、使用遊標的幾個注意事項

一、在使用遊標前,必須聲明(定義)它;這個過程實際沒有檢索數據,只是定義要使用的select語句;

二、一旦聲明,則必須打開遊標以供使用(這個過程用前面定義的select語句把數據實際檢索出來);

三、對於填有數據的遊標,根據須要取出(檢索)各行;

四、結束遊標使用時,必須關閉遊標。

 

2、觸發器

MySQL語句在須要時被執行,存儲過程也是如此,若是但願某條語句(或某些語句)在事件發生時自動執行,這就須要用到觸發器。

觸發器是MySQL響應如下任意語句而自動執行的一條MySQL語句(或位於begin和end語句之間的一組語句):delete;insert;update。其餘MySQL語句不支持觸發器。

 

1、建立觸發器

須要的信息:惟一的觸發器名;觸發器關聯的表;觸發器應該響應的活動(delete、insert或update);觸發器什麼時候執行(處理以前或以後)。

PSMySQL中,觸發器名必須在每一個表中惟一,但不是在每一個數據庫中惟一。即:同一數據庫中兩個表能夠具備相同名字的觸發器,但其餘的DBMS中不被容許,因此最好是在數據庫範圍內使用惟一的觸發器名。

觸發器使用create teigger語句建立,如:

create trigger newproduct after insert on products
for each row select 'product added';

建立newproduct觸發器,給出了after insert,因此此觸發器在insert語句成功執行後執行;還指定了for each row,所以代碼對每一個插入行執行。

PS

一、只有表才支持觸發器,視圖不支持(臨時表也不支持)。

二、觸發器按每一個表每一個事件每次的定義,每一個表每一個事件每次只容許一個觸發器;所以每一個表最多支持6個觸發器(每條insert、update和delete的以前和以後),單一觸發器不能與多個事件或多個表關聯。

三、若是before觸發器失敗,則MySQL將不執行請求的操做;此外,若是before觸發器或語句自己失敗,MySQL將不執行after觸發器(若是有的話)。

 

2、刪除觸發器

刪除觸發器用drop trigger語句,如:

drop trigger newproduct;

PS觸發器不能更新或覆蓋;爲了修改一個觸發器,必須先刪再建。

 

3、使用觸發器

1、insert觸發器

使用insert觸發器,須要知道如下三點:

一、在insert觸發器代碼內,可引用一個名爲new的虛擬表,訪問被插入的行;

二、在before insert觸發器內,new中的值也能夠被更新(容許更改被插入的值);

三、對於auto increment列,new在insert執行以前包含0,在insert執行以後包含新的自動生成值;

對於AUTO_INCREMENT自動賦予的值,肯定新生成值的方法,例子以下:

create trigger neworder after insert on orders
for each row select new.order_num;

建立一個名爲neworder的觸發器,按照after insert on order執行;在插入一條新的數據到orders表時,MySQL生成一個新訂單號並保存到order_num中;

觸發器從new.order_num取這個值並返回它;此觸發器必須按照after insert執行,由於在before insert語句執行以前,新order_num還沒生成。

PS一般將before用於數據驗證和淨化(目的是保證插入表中的數據確實是須要的數據)。這個規則也適用於update觸發器。

 

2、delete觸發器

使用delete觸發器,須要知道如下兩點:

一、在delete觸發器代碼內,能夠引用一個名爲old的虛擬表,訪問被刪除的行;

二、old中的值全都是隻讀的,不能更新;

使用old保存將要被刪除的行到一個存檔表中:

create trigger deleteorder before delete on orders
for each row
begin
    insert into archive_orders(order_num,order_date,cust_id)
    values(OLD_order_num, OLD_order_date, OLD_cust_id);
end;

在任意數據被刪除前執行此觸發器;它使用insert語句將old中的值(要被刪除的數據)保存到一個名爲archive_orders的存檔表中;

PS使用begin end塊的好處是觸發器能容納多條SQL語句。

 

3、update觸發器

使用update觸發器,須要知道如下三點:

一、在update觸發器代碼內,能夠引用一個名爲old的虛擬表訪問之前(update語句前)的值,引用一個名爲new的虛擬表訪問新更新的值;

二、在before update觸發器中,new中的值可能也被更新(容許更改將要用於update語句中的值);

三、old中的值全都是隻讀的,不能更新;

下面的例子,保證了州名稱縮寫老是大寫:

create trigger updateevendor before update on vendors
for each row set new.vend_state = upper(new.vend_state);

每次更新一個行時,new.vend_state中的值都用upper(new.vend_state)替換。

 

4、關於觸發器一些必須知道的知識:

一、建立觸發器可能須要特殊的安全訪問權限,但觸發器的執行是自動的。若是insert、update或delete語句能夠執行,則相應觸發器也能執行;

二、應該用觸發器來保證數據的一致性(大小寫、格式等);優勢在於它老是進行這種處理,並且是透明的進行,與客戶機應用無關;

三、觸發器的一種很是有意義的使用是建立審計跟蹤。使用觸發器,把更改記錄到另外一個表很是容易;

四、MySQL觸發器不支持call語句,即不能從觸發器內調用存儲過程。所需的存儲過程代碼須要複製到觸發器內。

相關文章
相關標籤/搜索