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ā)程序的二進制日志功能”里所說的,存儲子程序的二進制日志功能已經完成。 存儲程序需要在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.1. CREATE PROCEDURE和CREATE FUNCTION 20.2.2. ALTER PROCEDURE和ALTER FUNCTION 20.2.3. DROP PROCEDURE和DROP FUNCTION 20.2.4. SHOW CREATE PROCEDURE和SHOW CREATE FUNCTION 存儲程序和函數(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ù)的語法。 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ù)(或它的同義詞)或 當前來講,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ù)返回的值是字符串。 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語句中,可以指定超過一個的改變。 DROP {PROCEDURE | FUNCTION} [IF EXISTS] sp_name 這個語句被用來移除一個存儲程序或函數(shù)。即,從服務器移除一個制定的子程序。在MySQL 5.1中,你必須有ALTER ROUTINE權限才可用此子程序。這個權限被自動授予子程序的創(chuàng)建者。 IF EXISTS 子句是一個MySQL的擴展。如果程序或函數(shù)不存儲,它防止發(fā)生錯誤。產生一個可以用SHOW WARNINGS查看的警告。 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,'!')
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 表”。 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ù)來獲得。 [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)?/)使得; 可被用在子程序體中。 DECLARE語句被用來把不同項目局域到一個子程序:局部變量(請參閱20.2.9節(jié),“存儲程序中的變量”),條件和處理程序(請參閱20.2.10節(jié),“條件和處理程序”) 及光標(請參閱20.2.11節(jié),“光標”)。SIGNAL和RESIGNAL語句當前還不被支持。 DECLARE僅被用在BEGIN ... END復合語句里,并且必須在復合語句的開頭,在任何其它語句之前。 光標必須在聲明處理程序之前被聲明,并且變量和條件必須在聲明光標或處理程序之前被聲明。 你可以在子程序中聲明并使用變量。 DECLARE var_name[,...] type [DEFAULT value]
這個語句被用來聲明局部變量。要給變量提供一個默認值,請包含一個DEFAULT子句。值可以被指定為一個表達式,不需要為一個常數(shù)。如果沒有DEFAULT子句,初始值為NULL。 局部變量的作用范圍在它被聲明的BEGIN ... END塊內。它可以被用在嵌套的塊中,除了那些用相同名字聲明變量的塊。 SET var_name = expr [, var_name = expr] ... 在存儲程序中的SET語句是一般SET語句的擴展版本。被參考變量可能是子程序內聲明的變量,或者是全局服務器變量。 在存儲程序中的SET語句作為預先存在的SET語法的一部分來實現(xiàn)。這允許SET a=x, b=y, ...這樣的擴展語法。其中不同的變量類型(局域聲明變量及全局和集體變量)可以被混合起來。這也允許把局部變量和一些只對系統(tǒng)變量有意義的選項合并起來。在那種情況下,此選項被識別,但是被忽略了。 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’。 特定條件需要特定處理。這些條件可以聯(lián)系到錯誤,以及子程序中的一般流程控制。 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錯誤代碼。 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。 簡單光標在存儲程序和函數(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
DECLARE cursor_name CURSOR FOR select_statement
這個語句聲明一個光標。也可以在子程序中定義多個光標,但是一個塊中的每一個光標必須有唯一的名字。 SELECT語句不能有INTO子句。 IF, CASE, LOOP, WHILE, ITERATE, 及 LEAVE 構造被完全實現(xiàn)。 這些構造可能每個包含要么一個單獨語句,要么是使用BEGIN ... END復合語句的一塊語句。構造可以被嵌套。 目前還不支持FOR循環(huán)。 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ù)”。 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來終止。 [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),它們必須是同樣的。 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
[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)
[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
|
|