日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

mysql存儲過程與函數(shù)

 惠所勇 2010-06-13
 MySQL 5.1版支持存儲程序和函數(shù)。一個存儲程序是可以被存儲在服務器中的一套SQL語句。一旦它被存儲了,客戶端不需要再重新發(fā)布單獨的語句,而是可以引用存儲程序來替代。
MySQL 5.1版支持存儲程序和函數(shù)。一個存儲程序是可以被存儲在服務器中的一套SQL語句。一旦它被存儲了,客戶端不需要再重新發(fā)布單獨的語句,而是可以引用存儲程序來替代。

下面一些情況下存儲程序尤其有用:

·         當用不同語言編寫多客戶應用程序,或多客戶應用程序在不同平臺上運行且需要執(zhí)行相同的數(shù)據庫操作之時。

·         安全極為重要之時。比如,銀行對所有普通操作使用存儲程序。這提供一個堅固而安全的環(huán)境,程序可以確保每一個操作都被妥善記入日志。在這樣一個設置中,應用程序和用戶不可能直接訪問數(shù)據庫表,但是僅可以執(zhí)行指定的存儲程序。

儲程序可以提供改良后的性能,因為只有較少的信息需要在服務器和客戶算之間傳送。代價是增加數(shù)據庫服務器系統(tǒng)的負荷,因為更多的工作在服務器這邊完成,更少的在客戶端(應用程序)那邊完成上。如果許多客戶端機器(比如網頁服務器)只由一個或少數(shù)幾個數(shù)據庫服務器提供服務,可以考慮一下存儲程序。

存儲程序也允許你在數(shù)據庫服務器上有函數(shù)庫。這是一個被現(xiàn)代應用程序語言共享的特征,它允許這樣的內部設計,比如通過使用類。使用這些客戶端應用程序語言特征對甚至于數(shù)據庫使用范圍以外的編程人員都有好處。

MySQL為存儲程序遵循SQL:2003語法,這個語法也被用在IBM的DB2數(shù)據庫上。

MySQL對存儲程序的實現(xiàn)還在進度中。所有本章敘述的語法都被支持,在有限制或擴展的地方會恰當?shù)刂赋鰜?。有關使用存儲程序的限制的更多討論在附錄 I, 特性限制里提到。

20.4節(jié),“存儲子程序和觸發(fā)程序的二進制日志功能”里所說的,存儲子程序的二進制日志功能已經完成。

20.1. 存儲程序和授權表

存儲程序需要在mysql數(shù)據庫中有proc表。這個表在MySQL 5.1安裝過程中創(chuàng)建。如果你從早期的版本升級到MySQL 5.1 ,請確定更新你的授權表以確保proc表的存在。請參閱2.10.2節(jié) “升級授權表”。

在MySQL 5.1中,授權系統(tǒng)如下考慮存儲子程序:

·         創(chuàng)建存儲子程序需要CREATE ROUTINE權限。

·         提醒或移除存儲子程序需要ALTER ROUTINE權限。這個權限自動授予子程序的創(chuàng)建者。

·         執(zhí)行子程序需要EXECUTE權限。然而,這個權限自動授予子程序的創(chuàng)建者。同樣,子程序默認的SQL SECURITY 特征是DEFINER,它允許用該子程序訪問數(shù)據庫的用戶與執(zhí)行子程序聯(lián)系到一起。

20.2. 存儲程序的語法

存儲程序和函數(shù)是用CREATE PROCEDURE和CREATE FUNCTION語句創(chuàng)建的子程序。一個子程序要么是一個程序要么是一個函數(shù)。使用CALL語句來調用程序,程序只能用輸出變量傳回值。就像別其它函數(shù)調用一樣,函數(shù)可以被從語句外調用(即通過引用函數(shù)名),函數(shù)能返回標量值。存儲子程序也可以調用其它存儲子程序。

在MySQL 5.1中,一個存儲子程序或函數(shù)與特定的數(shù)據庫相聯(lián)系。這里有幾個意思:

·         當一個子程序被調用時,一個隱含的USE db_name 被執(zhí)行(當子程序終止時停止執(zhí)行)。存儲子程序內的USE語句時不允許的。

·         你可以使用數(shù)據庫名限定子程序名。這可以被用來引用一個不在當前數(shù)據庫中的子程序。比如,要引用一個與test數(shù)據庫關聯(lián)的存儲程序p或函數(shù)f,你可以說CALL test.p()或test.f()。

·         數(shù)據庫移除的時候,與它關聯(lián)的所有存儲子程序也都被移除。

MySQL 支持非常有用的擴展,即它允許在存儲程序中使用常規(guī)的SELECT語句(那就是說,不使用光標或局部變量)。這個一個查詢的結果包被簡單地直接送到客戶端。多SELECT語句生成多個結果包,所以客戶端必須使用支持多結果包的MySQL客戶端庫。這意味這客戶端必須使用至少MySQL 4.1以來的近期版本上的客戶端庫。

下面一節(jié)描述用來創(chuàng)建,改變,移除和查詢存儲程序和函數(shù)的語法。

20.2.1CREATE PROCEDURECREATE FUNCTION

CREATE PROCEDURE sp_name ([proc_parameter[,...]])
    [characteristic ...] routine_body
 
CREATE FUNCTION sp_name ([func_parameter[,...]])
    RETURNS type
    [characteristic ...] routine_body
    
    proc_parameter:
    [ IN | OUT | INOUT ] param_name type
    
    func_parameter:
    param_name type
 
type:
    Any valid MySQL data type
 
characteristic:
    LANGUAGE SQL
  | [NOT] DETERMINISTIC
  | { CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA }
  | SQL SECURITY { DEFINER | INVOKER }
  | COMMENT 'string'
 
routine_body:
    Valid SQL procedure statement or statements

這些語句創(chuàng)建存儲子程序。要在MySQL 5.1中創(chuàng)建子程序,必須具有CREATE ROUTINE權限,并且ALTER ROUTINE和EXECUTE權限被自動授予它的創(chuàng)建者。如果二進制日志功能被允許,你也可能需要SUPER權限,請參閱20.4節(jié),“存儲子程序和觸發(fā)程序的二進制日志功能”。

默認地,子程序與當前數(shù)據庫關聯(lián)。要明確地把子程序與一個給定數(shù)據庫關聯(lián)起來,可以在創(chuàng)建子程序的時候指定其名字為db_name.sp_name。

如果子程序名和內建的SQL函數(shù)名一樣,定義子程序時,你需要在這個名字和隨后括號中間插入一個空格,否則發(fā)生語法錯誤。當你隨后調用子程序的時候也要插入。為此,即使有可能出現(xiàn)這種情況,我們還是建議最好避免給你自己的存儲子程序取與存在的SQL函數(shù)一樣的名字。

由括號包圍的參數(shù)列必須總是存在。如果沒有參數(shù),也該使用一個空參數(shù)列()。每個參數(shù)默認都是一個IN參數(shù)。要指定為其它參數(shù),可在參數(shù)名之前使用關鍵詞 OUT或INOUT

注意: 指定參數(shù)為IN, OUT, 或INOUT 只對PROCEDURE是合法的。(FUNCTION參數(shù)總是被認為是IN參數(shù))

RETURNS字句只能對FUNCTION指定,對函數(shù)而言這是強制的。它用來指定函數(shù)的返回類型,而且函數(shù)體必須包含一個RETURN value語句。

routine_body 包含合法的SQL過程語句??梢允褂脧秃险Z句語法,請參閱20.2.7節(jié),“BEGIN ... END復合語句。復合語句可以包含聲明,循環(huán)和其它控制結構語句。這些語句的語法在本章后免介紹,舉例,請參閱20.2.8節(jié),“DECLARE語句20.2.12節(jié),“流程控制構造”。

CREATE FUNCTION語句被用在更早的MySQL版本上支持UDF (自定義函數(shù))。請參閱27.2節(jié),“給MySQL添加新函數(shù)”。 UDF繼續(xù)被支持,即使現(xiàn)在有了存儲函數(shù)。UDF會被認為一個外部存儲函數(shù)。然而,不要讓存儲函數(shù)與UDF函數(shù)共享名字空間。

外部存儲程序的框架將在不久的將來引入。這將允許你用SQL之外的語言編寫存儲程序。最可能的是,第一個被支持語言是PHP,因為核心PHP引擎很小,線程安全,且可以被方便地嵌入。因為框架是公開的,它希望許多其它語言也能被支持。

如果程序或線程總是對同樣的輸入參數(shù)產生同樣的結果,則被認為它是“確定的”,否則就是“非確定”的。如果既沒有給定DETERMINISTIC也沒有給定NOT DETERMINISTIC,默認的就是NOT DETERMINISTIC。

為進行復制,使用NOW()函數(shù)(或它的同義詞)或RAND()函數(shù)會不必要地使得一個子程序非確定。對NOW()而言,二進制日志包括時間戳并被正確復制。RAND() 只要在一個子程序被內應用一次也會被正確復制。(你可以把子程序執(zhí)行時間戳和隨機數(shù)種子認為強制輸入,它們在主從上是同樣的。)

當前來講,DETERMINISTIC特征被接受,但還沒有被優(yōu)化程序所使用。然而如果二進制日志功能被允許了,這個特征影響到MySQL是否會接受子程序定義。請參閱20.4節(jié),“存儲子程序和觸發(fā)程序的二進制日志功能”。

一些特征提供子程序使用數(shù)據的內在信息。CONTAINS SQL表示子程序不包含讀或寫數(shù)據的語句。NO SQL表示子程序不包含SQL語句。READS SQL DATA表示子程序包含讀數(shù)據的語句,但不包含寫數(shù)據的語句。MODIFIES SQL DATA表示子程序包含寫數(shù)據的語句。如果這些特征沒有明確給定,默認的是CONTAINS SQL。

SQL SECURITY特征可以用來指定 子程序該用創(chuàng)建子程序者的許可來執(zhí)行,還是使用調用者的許可來執(zhí)行。默認值是DEFINER。在SQL:2003中者是一個新特性。創(chuàng)建者或調用者必須由訪問子程序關聯(lián)的數(shù)據庫的許可。在MySQL 5.1中,必須有EXECUTE權限才能執(zhí)行子程序。必須擁有這個權限的用戶要么是定義者,要么是調用者,這取決于SQL SECURITY特征是如何設置的。

MySQL存儲sql_mode系統(tǒng)變量設置,這個設置在子程序被創(chuàng)建的時候起作用,MySQL總是強制使用這個設置來執(zhí)行子程序。

COMMENT子句是一個MySQL的擴展,它可以被用來描述存儲程序。這個信息被SHOW CREATE PROCEDURE和 SHOW CREATE FUNCTION語句來顯示。

MySQL允許子程序包含DDL語句,如CREATE和DROP。MySQL也允許存儲程序(但不是存儲函數(shù))包含SQL 交互語句,如COMMIT。存儲函數(shù)不可以包含那些做明確的和絕對的提交或者做回滾的語。SQL標準不要求對這些語句的支持,SQL標準聲明每個DBMS提供商可以決定是否允許支持這些語句。

存儲子程序不能使用LOAD DATA INFILE。

返回結果包的語句不能被用在存儲函數(shù)種。這包括不使用INTO給變量讀取列值的SELECT語句,SHOW 語句,及其它諸如EXPLAIN這樣的語句。對于可在函數(shù)定義時間被決定要返回一個結果包的語句,發(fā)生一個允許從函數(shù)錯誤返回結果包的Not(ER_SP_NO_RETSET_IN_FUNC)。對于只可在運行時決定要返回一個結果包的語句, 發(fā)生一個不能在給定上下文錯誤返回結果包的PROCEDURE %s (ER_SP_BADSELECT)。

下面是一個使用OUT參數(shù)的簡單的存儲程序的例子。例子為,在程序被定義的時候,用mysql客戶端delimiter命令來把語句定界符從 ;變?yōu)?/。這就允許用在程序體中的;定界符被傳遞到服務器而不是被mysql自己來解釋。

mysql> delimiter //
 
mysql> CREATE PROCEDURE simpleproc (OUT param1 INT)
    -> BEGIN
    ->   SELECT COUNT(*) INTO param1 FROM t;
    -> END
    -> //
Query OK, 0 rows affected (0.00 sec)
 
mysql> delimiter ;
 
mysql> CALL simpleproc(@a);
Query OK, 0 rows affected (0.00 sec)
 
mysql> SELECT @a;
+------+
| @a   |
+------+
| 3    |
+------+
1 row in set (0.00 sec)

當使用delimiter命令時,你應該避免使用反斜杠(\)字符,因為那是MySQL的轉義字符。

下列是一個例子,一個采用參數(shù)的函數(shù)使用一個SQL函數(shù)執(zhí)行一個操作,并返回結果:

mysql> delimiter //
 
mysql> CREATE FUNCTION hello (s CHAR(20)) RETURNS CHAR(50)
    -> RETURN CONCAT('Hello, ',s,'!');
    -> //
Query OK, 0 rows affected (0.00 sec)
 
mysql> delimiter ;
 
mysql> SELECT hello('world');
+----------------+
| hello('world') |
+----------------+
| Hello, world!  |
+----------------+
1 row in set (0.00 sec)

如果在存儲函數(shù)中的RETURN語句返回一個類型不同于在函數(shù)的RETURNS子句中指定類型的值,返回值被強制為恰當?shù)念愋汀1热?,如果一個函數(shù)返回一個ENUM或SET值,但是RETURN語句返回一個整數(shù),對于SET成員集的相應的ENUM成員,從函數(shù)返回的值是字符串。

20.2.2. ALTER PROCEDUREALTER FUNCTION

ALTER {PROCEDURE | FUNCTION} sp_name [characteristic ...]
 
characteristic:
    { CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA }
  | SQL SECURITY { DEFINER | INVOKER }
  | COMMENT 'string'

這個語句可以被用來改變一個存儲程序或函數(shù)的特征。在MySQL 5.1中,你必須用ALTER ROUTINE權限才可用此子程序。這個權限被自動授予子程序的創(chuàng)建者。如20.4節(jié),“存儲子程序和觸發(fā)程序的二進制日志功能”中所述, 如果二進制日志功能被允許了,你可能也需要SUPER權限。

在ALTER PROCEDURE和ALTER FUNCTION語句中,可以指定超過一個的改變。

20.2.3. DROP PROCEDUREDROP FUNCTION

DROP {PROCEDURE | FUNCTION} [IF EXISTS] sp_name

這個語句被用來移除一個存儲程序或函數(shù)。即,從服務器移除一個制定的子程序。在MySQL 5.1中,你必須有ALTER ROUTINE權限才可用此子程序。這個權限被自動授予子程序的創(chuàng)建者。

IF EXISTS 子句是一個MySQL的擴展。如果程序或函數(shù)不存儲,它防止發(fā)生錯誤。產生一個可以用SHOW WARNINGS查看的警告。

20.2.4. SHOW CREATE PROCEDURESHOW CREATE FUNCTION

SHOW CREATE {PROCEDURE | FUNCTION} sp_name

這個語句是一個MySQL的擴展。類似于SHOW CREATE TABLE,它返回一個可用來重新創(chuàng)建已命名子程序的確切字符串。

mysql> SHOW CREATE FUNCTION test.hello\G
*************************** 1. row ***************************
       Function: hello
       sql_mode:
Create Function: CREATE FUNCTION `test`.`hello`(s CHAR(20)) RETURNS CHAR(50)
RETURN CONCAT('Hello, ',s,'!')

20.2.5. SHOW PROCEDURE STATUSSHOW FUNCTION STATUS

SHOW {PROCEDURE | FUNCTION} STATUS [LIKE 'pattern']

這個語句是一個MySQL的擴展。它返回子程序的特征,如數(shù)據庫,名字,類型,創(chuàng)建者及創(chuàng)建和修改日期。如果沒有指定樣式,根據你使用的語句,所有存儲程序和所有存儲函數(shù)的信息都被列出。

mysql> SHOW FUNCTION STATUS LIKE 'hello'\G
*************************** 1. row ***************************
           Db: test
         Name: hello
         Type: FUNCTION
      Definer: testuser@localhost
     Modified: 2004-08-03 15:29:37
      Created: 2004-08-03 15:29:37
Security_type: DEFINER
      Comment:

你可以從INFORMATION_SCHEMA中的ROUTINES表獲得有關存儲子程序的信息。請參閱23.1.14節(jié),“INFORMATION_SCHEMA ROUTINES 表。

20.2.6. CALL語句

CALL sp_name([parameter[,...]])

CALL語句調用一個先前用CREATE PROCEDURE創(chuàng)建的程序。

CALL語句可以用聲明為OUT或的INOUT參數(shù)的參數(shù)給它的調用者傳回值。它也“返回”受影響的行數(shù),客戶端程序可以在SQL級別通過調用ROW_COUNT()函數(shù)獲得這個數(shù),從C中是調用the mysql_affected_rows() C API函數(shù)獲得。

20.2.7. BEGIN ... END復合語句

[begin_label:] BEGIN
    [statement_list]
END [end_label]

存儲子程序可以使用BEGIN ... END復合語句來包含多個語句。statement_list 代表一個或多個語句的列表。statement_list之內每個語句都必須用分號(;)來結尾。

復合語句可以被標記。除非begin_label存在,否則end_label不能被給出,并且如果二者都存在,他們必須是同樣的。

請注意,可選的[NOT] ATOMIC子句現(xiàn)在還不被支持。這意味著在指令塊的開始沒有交互的存儲點被設置,并且在上下文中用到的BEGIN子句對當前交互動作沒有影響。

使用多重語句需要客戶端能發(fā)送包含語句定界符;的查詢字符串。這個符號在命令行客戶端被用delimiter命令來處理。改變查詢結尾定界符;(比如改變?yōu)?/)使得; 可被用在子程序體中。

20.2.8. DECLARE語句

DECLARE語句被用來把不同項目局域到一個子程序:局部變量(請參閱20.2.9節(jié),“存儲程序中的變量”),條件和處理程序(請參閱20.2.10節(jié),“條件和處理程序”) 及光標(請參閱20.2.11節(jié),“光標”)。SIGNAL和RESIGNAL語句當前還不被支持。

DECLARE僅被用在BEGIN ... END復合語句里,并且必須在復合語句的開頭,在任何其它語句之前。

光標必須在聲明處理程序之前被聲明,并且變量和條件必須在聲明光標或處理程序之前被聲明。

20.2.9. 存儲程序中的變量

你可以在子程序中聲明并使用變量。

20.2.9.1. DECLARE局部變量

DECLARE var_name[,...] type [DEFAULT value]

這個語句被用來聲明局部變量。要給變量提供一個默認值,請包含一個DEFAULT子句。值可以被指定為一個表達式,不需要為一個常數(shù)。如果沒有DEFAULT子句,初始值為NULL。

局部變量的作用范圍在它被聲明的BEGIN ... END塊內。它可以被用在嵌套的塊中,除了那些用相同名字聲明變量的塊。

20.2.9.2. 變量SET語句

SET var_name = expr [, var_name = expr] ...

在存儲程序中的SET語句是一般SET語句的擴展版本。被參考變量可能是子程序內聲明的變量,或者是全局服務器變量。

在存儲程序中的SET語句作為預先存在的SET語法的一部分來實現(xiàn)。這允許SET a=x, b=y, ...這樣的擴展語法。其中不同的變量類型(局域聲明變量及全局和集體變量)可以被混合起來。這也允許把局部變量和一些只對系統(tǒng)變量有意義的選項合并起來。在那種情況下,此選項被識別,但是被忽略了。

20.2.9.3. SELECT ... INTO語句

SELECT col_name[,...] INTO var_name[,...] table_expr

這個SELECT語法把選定的列直接存儲到變量。因此,只有單一的行可以被取回。

SELECT id,data INTO x,y FROM test.t1 LIMIT 1;

注意,用戶變量名在MySQL 5.1中是對大小寫不敏感的。請參閱9.3節(jié),“用戶變量”。

重要: SQL變量名不能和列名一樣。如果SELECT ... INTO這樣的SQL語句包含一個對列的參考,并包含一個與列相同名字的局部變量,MySQL當前把參考解釋為一個變量的名字。例如,在下面的語句中,xname 被解釋為到xname variable 的參考而不是到xname column的:

CREATE PROCEDURE sp1 (x VARCHAR(5))
  BEGIN
    DECLARE xname VARCHAR(5) DEFAULT 'bob';
    DECLARE newname VARCHAR(5);
    DECLARE xid INT;
    
    SELECT xname,id INTO newname,xid 
      FROM table1 WHERE xname = xname;
    SELECT newname;
  END;

當這個程序被調用的時候,無論table.xname列的值是什么,變量newname將返回值‘bob’。

請參閱I.1節(jié),“存儲子程序和觸發(fā)程序的限制”

20.2.10. 條件和處理程序

特定條件需要特定處理。這些條件可以聯(lián)系到錯誤,以及子程序中的一般流程控制。

20.2.10.1. DECLARE條件

DECLARE condition_name CONDITION FOR condition_value
 
condition_value:
    SQLSTATE [VALUE] sqlstate_value
  | mysql_error_code

這個語句指定需要特殊處理的條件。它將一個名字和指定的錯誤條件關聯(lián)起來。這個名字可以隨后被用在DECLARE HANDLER語句中。請參閱20.2.10.2節(jié),“DECLARE處理程序。

除了SQLSTATE值,也支持MySQL錯誤代碼。

20.2.10.2. DECLARE處理程序

DECLARE handler_type HANDLER FOR condition_value[,...] sp_statement
 
handler_type:
    CONTINUE
  | EXIT
  | UNDO
 
condition_value:
    SQLSTATE [VALUE] sqlstate_value
  | condition_name
  | SQLWARNING
  | NOT FOUND
  | SQLEXCEPTION
  | mysql_error_code

這個語句指定每個可以處理一個或多個條件的處理程序。如果產生一個或多個條件,指定的語句被執(zhí)行。

對一個CONTINUE處理程序,當前子程序的執(zhí)行在執(zhí)行處理程序語句之后繼續(xù)。對于EXIT處理程序,當前BEGIN...END復合語句的執(zhí)行被終止。UNDO 處理程序類型語句還不被支持。

·         SQLWARNING是對所有以01開頭的SQLSTATE代碼的速記。

·         NOT FOUND是對所有以02開頭的SQLSTATE代碼的速記。

·         SQLEXCEPTION是對所有沒有被SQLWARNING或NOT FOUND捕獲的SQLSTATE代碼的速記。

除了SQLSTATE值,MySQL錯誤代碼也不被支持。

例如:

mysql> CREATE TABLE test.t (s1 int,primary key (s1));
Query OK, 0 rows affected (0.00 sec)
 
mysql> delimiter //
 
mysql> CREATE PROCEDURE handlerdemo ()
    -> BEGIN
    ->   DECLARE CONTINUE HANDLER FOR SQLSTATE '23000' SET @x2 = 1;
    ->   SET @x = 1;
    ->   INSERT INTO test.t VALUES (1);
    ->   SET @x = 2;
    ->   INSERT INTO test.t VALUES (1);
    ->   SET @x = 3;
    -> END;
    -> //
Query OK, 0 rows affected (0.00 sec)
 
mysql> CALL handlerdemo()//
Query OK, 0 rows affected (0.00 sec)
 
mysql> SELECT @x//
    +------+
    | @x   |
    +------+
    | 3    |
    +------+
    1 row in set (0.00 sec)

注意到,@x是3,這表明MySQL被執(zhí)行到程序的末尾。如果DECLARE CONTINUE HANDLER FOR SQLSTATE '23000' SET @x2 = 1; 這一行不在,第二個INSERT因PRIMARY KEY強制而失敗之后,MySQL可能已經采取默認(EXIT)路徑,并且SELECT @x可能已經返回2。

20.2.11. 光標

簡單光標在存儲程序和函數(shù)內被支持。語法如同在嵌入的SQL中。光標當前是不敏感的,只讀的及不滾動的。不敏感意為服務器可以活不可以復制它的結果表。

光標必須在聲明處理程序之前被聲明,并且變量和條件必須在聲明光標或處理程序之前被聲明。

例如:

CREATE PROCEDURE curdemo()
BEGIN
  DECLARE done INT DEFAULT 0;
  DECLARE a CHAR(16);
  DECLARE b,c INT;
  DECLARE cur1 CURSOR FOR select id,data FROM test.t1;
  DECLARE cur2 CURSOR FOR select i FROM test.t2;
  DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done = 1;
 
  OPEN cur1;
  OPEN cur2;
 
  REPEAT
    FETCH cur1 INTO a, b;
    FETCH cur2 INTO c;
    IF NOT done THEN
       IF b < c THEN
          INSERT INTO test.t3 VALUES (a,b);
       ELSE
          INSERT INTO test.t3 VALUES (a,c);
       END IF;
    END IF;
  UNTIL done END REPEAT;
 
  CLOSE cur1;
  CLOSE cur2;
END

20.2.11.1.聲明光標

DECLARE cursor_name CURSOR FOR select_statement

這個語句聲明一個光標。也可以在子程序中定義多個光標,但是一個塊中的每一個光標必須有唯一的名字。

SELECT語句不能有INTO子句。

20.2.11.2. 光標OPEN語句

OPEN cursor_name

這個語句打開先前聲明的光標。

20.2.11.3. 光標FETCH語句

FETCH cursor_name INTO var_name [, var_name] ...

這個語句用指定的打開光標讀取下一行(如果有下一行的話),并且前進光標指針。

20.2.11.4. 光標CLOSE語句

CLOSE cursor_name

這個語句關閉先前打開的光標。

如果未被明確地關閉,光標在它被聲明的復合語句的末尾被關閉。

20.2.12. 流程控制構造

IF, CASE, LOOP, WHILE, ITERATE, 及 LEAVE 構造被完全實現(xiàn)。

這些構造可能每個包含要么一個單獨語句,要么是使用BEGIN ... END復合語句的一塊語句。構造可以被嵌套。

目前還不支持FOR循環(huán)。

20.2.12.1. IF語句

IF search_condition THEN statement_list
    [ELSEIF search_condition THEN statement_list] ...
    [ELSE statement_list]
END IF

IF實現(xiàn)了一個基本的條件構造。如果search_condition求值為真,相應的SQL語句列表被執(zhí)行。如果沒有search_condition匹配,在ELSE子句里的語句列表被執(zhí)行。statement_list可以包括一個或多個語句。

請注意,也有一個IF() 函數(shù),它不同于這里描述的IF語句。請參閱12.2節(jié),“控制流程函數(shù)”

20.2.12.2. CASE語句

CASE case_value
    WHEN when_value THEN statement_list
    [WHEN when_value THEN statement_list] ...
    [ELSE statement_list]
END CASE

Or:

CASE
    WHEN search_condition THEN statement_list
    [WHEN search_condition THEN statement_list] ...
    [ELSE statement_list]
END CASE

存儲程序的CASE語句實現(xiàn)一個復雜的條件構造。如果search_condition 求值為真,相應的SQL被執(zhí)行。如果沒有搜索條件匹配,在ELSE子句里的語句被執(zhí)行。

注意:這里介紹的用在存儲程序里的CASE語句與12.2節(jié),“控制流程函數(shù)”里描述的SQL CASE表達式的CASE語句有輕微不同。這里的CASE語句不能有ELSE NULL子句,并且用END CASE替代END來終止。

20.2.12.3. LOOP語句

[begin_label:] LOOP
    statement_list
END LOOP [end_label]

LOOP允許某特定語句或語句群的重復執(zhí)行,實現(xiàn)一個簡單的循環(huán)構造。在循環(huán)內的語句一直重復直循環(huán)被退出,退出通常伴隨著一個LEAVE 語句。

LOOP語句可以被標注。除非begin_label存在,否則end_label不能被給出,并且如果兩者都出現(xiàn),它們必須是同樣的。

20.2.12.4. LEAVE語句

LEAVE label

這個語句被用來退出任何被標注的流程控制構造。它和BEGIN ... END或循環(huán)一起被使用。

20.2.12.5. ITERATE語句

ITERATE label

ITERATE只可以出現(xiàn)在LOOP, REPEAT, 和WHILE語句內。ITERATE意思為:“再次循環(huán)。”

例如:

CREATE PROCEDURE doiterate(p1 INT)
BEGIN
  label1: LOOP
    SET p1 = p1 + 1;
    IF p1 < 10 THEN ITERATE label1; END IF;
    LEAVE label1;
  END LOOP label1;
  SET @x = p1;
END

20.2.12.6. REPEAT語句

[begin_label:] REPEAT
    statement_list
UNTIL search_condition
END REPEAT [end_label]

REPEAT語句內的語句或語句群被重復,直至search_condition 為真。

REPEAT 語句可以被標注。 除非begin_label也存在,end_label才能被用,如果兩者都存在,它們必須是一樣的。

例如

mysql> delimiter //
 
mysql> CREATE PROCEDURE dorepeat(p1 INT)
    -> BEGIN
    ->   SET @x = 0;
    ->   REPEAT SET @x = @x + 1; UNTIL @x > p1 END REPEAT;
    -> END
    -> //
Query OK, 0 rows affected (0.00 sec)
 
mysql> CALL dorepeat(1000)//
Query OK, 0 rows affected (0.00 sec)
 
mysql> SELECT @x//
+------+
| @x   |
+------+
| 1001 |
+------+
1 row in set (0.00 sec)

20.2.12.7. WHILE語句

[begin_label:] WHILE search_condition DO
    statement_list
END WHILE [end_label]

WHILE語句內的語句或語句群被重復,直至search_condition 為真。

WHILE語句可以被標注。 除非begin_label也存在,end_label才能被用,如果兩者都存在,它們必須是一樣的。

例如:

CREATE PROCEDURE dowhile()
BEGIN
  DECLARE v1 INT DEFAULT 5;
 
  WHILE v1 > 0 DO
    ...
    SET v1 = v1 - 1;
  END WHILE;
END

    本站是提供個人知識管理的網絡存儲空間,所有內容均由用戶發(fā)布,不代表本站觀點。請注意甄別內容中的聯(lián)系方式、誘導購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權內容,請點擊一鍵舉報。
    轉藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多