MySQL存儲過程學習筆記

一、基本語法及簡單實例

1、創建簡單的測試環境

mysql> use test;
Database changed
mysql> show tables;
Empty set (0.00 sec)
 
mysql> CREATE TABLE t(s1 INT);
Query OK, 0 rows affected (0.06 sec)
 
mysql> INSERT INTO t VALUES(5);
Query OK, 1 row affected (0.02 sec)

2、選擇分隔符

mysql> DELIMITER //

我們一般使用";"作爲分隔符,但是在編寫存儲過程的時候這會帶來一些問題,因爲存儲過程中有許多語句,修改會";"作爲分隔符可使用語句"DELIMITER ;//"。

3、創建存儲過程

mysql> CREATE PROCEDURE p1() SELECT * FROM t;//
Query OK, 0 rows affected (0.08 sec)

"CREATE PROCEDURE"即爲SQL語句部分,第二部分是過程名"p1"(這裏需要注意的是存儲過程名對大小寫不敏感)。

第三部分 () 是參數列表,通常需要在其中添加參數,這裏參數爲空,但是"()"必須存在。

"SELECT * FROM t;"是存儲過程的主體,注意哦,";"是主體的一部分哦,創建該存儲過程的語句的真正結束符爲"//"。

另外需要注意的一點是,和我們創建表一樣,在創建存儲過程前面需要檢查是否存在同名的存儲過程,即" DROP PROCEDURE IF EXISTS p1;",沒錯這正是刪除一個存儲過程的SQL語句。另外,不能在一個存儲過程中刪除另一個存儲過程,只能調用另一個存儲過程。

4、調用存儲過程

mysql> CALL p1()//
+------+
| s1   |
+------+
|    5 |
+------+
1 row in set (0.00 sec)
 
Query OK, 0 rows affected (0.00 sec)

這裏只是簡單的調用,在下一點關於參數的使用辦法中有更爲複雜的調用。

5、參數(Parameter)

mysql> CREATE PROCEDURE p2(p INT) SET @x = p ;//
Query OK, 0 rows affected (0.02 sec)
 
mysql> CALL p2(123)//
Query OK, 0 rows affected (0.00 sec)
 
mysql> SELECT @x//
+------+
| @x   |
+------+
|  123 |
+------+
1 row in set (0.01 sec)

這是輸入參數的例子,我們選擇了會話變量@x證明成功的將參數傳入了改變量。

mysql> CREATE PROCEDURE p3(OUT p INT)
    -> SET p = -5;//
Query OK, 0 rows affected (0.00 sec)
 
mysql> CALL p3(@y)//
Query OK, 0 rows affected (0.01 sec)
 
mysql> SELECT @y//
+------+
| @y   |
+------+
|   -5 |
+------+
1 row in set (0.00 sec)

這是輸出參數的例子,我們選擇會話變量@y去接收存儲過程p3輸出參數的值。

6、變量(Variables)

CREATE PROCEDURE P5()
BEGIN
 DECLARE a INT;
 DECLARE b INT;
 SET a = 5;
 SET b = 5;
 INSERT INTO t VALUES(a);
 SELECT s1 FROM t WHERE s1>= b;
END;
-------------------------------------------------
mysql> CALL p5();
+----+
| s1 |
+----+
|  5 |
|  5 |
+----+
2 rows in set
 
Query OK, 0 rows affected

在過程中定義的變量並不是真正的定義,你只是在BEGIN/END(即複合語句)塊內定義了而已。注意這些變量和會話變量不一樣,不能使用修飾符@你必須清楚的在BEGIN/END塊中聲明變量和它們的類型。變量一旦聲明,你就能在任何能使用會話變量、文字、列名的地方使用。還需要注意的一點是,在一個塊內,我們需要把所有要使用的變量先聲明,才能在後面使用,並且不能在聲明變量的語句間夾雜其他使用變量的語句,否會報語法錯誤。

CREATE PROCEDURE P6()
BEGIN
 DECLARE a,b INT DEFAULT 5;
 INSERT INTO t VALUES(a);
 SELECT s1 * a FROM t WHERE s1>= b;
END;
------------------------------------------------------
mysql> CALL p6();
+--------+
| s1 * a |
+--------+
|     25 |
|     25 |
|     25 |
+--------+

這裏使用DEFAULT子句來設定初始值,如此我們可以不需要把DECLARE和SET語句的實現分開。

7、區塊的定義使用

一般形式爲

begin
......
end;

也可以給區塊起別名,如:

lable:begin
...........
end lable;

可以用leave lable;跳出區塊,執行區塊以後的代碼。

8、條件語句

一般形式爲

if 條件 then
statement
else
statement
end if;

實例:

CREATE PROCEDURE p7(IN param1 INT)
BEGIN
 DECLARE v1 INT;
 SET v1 = param1 + 1;
 IF v1 = 0 THEN
   INSERT INTO t VALUES(17);
 END IF;
 IF param1 = 0 THEN
   UPDATE t SET s1 = s1 + 1;
 ELSE
   UPDATE t SET s1 = s1 + 2;
 END IF;
END;//
-----------------------------------------------------------
mysql> SELECT * FROM t;
+----+
| s1 |
+----+
|  6 |
|  6 |
|  6 |
+----+
3 rows in set
 
mysql> CALL p7(0);
Query OK, 3 rows affected
 
mysql> CALL p7(0);
Query OK, 3 rows affected
 
mysql> SELECT * FROM t;
+----+
| s1 |
+----+
|  8 |
|  8 |
|  8 |
+----+
3 rows in set

過程很簡單,可以看出調用兩次即執行了兩次UPDATE t SET s1= s1 + 1;語句。另外還有CASE指令,使用辦法和IF一樣簡單,簡單實例如下:

CREATE PROCEDURE p8(IN param1 INT)
BEGIN
 DECLARE v1 INT;
 SET v1 = param1 + 1;
 CASE v1
   WHEN 0 THEN INSERT INTO tVALUES(17);
   WHEN 1 THEN INSERT INTO tVALUES(18);
   ELSE INSERT INTO tVALUES(19);
 END CASE;
END;//


9、循環語句

1)while循環

[label:] WHILE expression DO
statements
END WHILE [label] ;

實例:

CREATE PROCEDURE p9 () 
BEGIN 
  DECLARE v INT; 
  SET v = 0; 
  WHILE v < 5 DO 
    INSERT INTO t VALUES(v); 
    SET v = v + 1; 
  END WHILE; 
END; // 


2)repeat until循環

[label:] REPEAT
statements
UNTIL expression
END REPEAT [label] ;

實例:

CREATE PROCEDURE p10 () 
BEGIN 
  DECLARE v INT; 
  SET v = 0; 
  REPEAT 
    INSERT INTO t VALUES(v); 
    SET v = v + 1; 
    UNTIL v >= 5                                     
  END REPEAT; 
END; //


3)loop循環

[label:] LOOP
statements
END LOOP[label];

實例:

CREATE PROCEDUREp11 () 
BEGIN 
  DECLARE v INT; 
  SET v = 0; 
  loop_label: LOOP 
    INSERT INTO t VALUES (v); 
    SET v = v + 1; 
    IF v >= 5 THEN 
      LEAVE loop_label; 
    END IF; 
  END LOOP; 
END; //


10、其他常用命令

1)showprocedure status

顯示數據庫中所有存儲的存儲過程基本信息,包括所屬數據庫,存儲過程名稱,創建時間等

2)show createprocedure sp_name

顯示某一個存儲過程的詳細信息

 

二、常見錯誤及處理辦法

1、[Err] 1064 -You have an error in your SQL syntax; check the manual that corresponds to yourMySQL server version for the right syntax to use near '***'

很簡單,1064即爲SQL語法錯誤,仔細檢查錯誤提示信息所指語句附近改正即可。

例:

CREATE PROCEDURE P12()
BEGIN
 DECLARE a INT;
 SET a = 5;
 DECLARE b INT;
 SET b = 5;
 INSERT INTO t VALUES(a);
 SELECT s1 FROM t WHERE s1>= b;
END;

提示信息爲:

[Err] 1064 - You have an error in your SQL syntax; check the manualthat corresponds to your MySQL server version for the right syntax to use near'DECLARE b INT;

        SET b = 5;

        INSERT INTO t VALUES(a);

        SELECT s1 FROM t WHE' at line 5

提示在第5行,我們發現在變量聲明語句"DECLARE b INT;"的前面有一條賦值語句"SET a = 5;",只需將其放到所有變量聲明語句之後即可。

2、[Err] 1318 -Incorrect number of arguments for PROCEDURE *.*; expected *, got *

如提示信息,database_name.procedure_name的存儲過程傳入的參數個數不對。

例:

CREATE PROCEDURE p13(OUT p INT)
SET p = -5;
CALL p13();

提示信息爲:

[Err] 1318 - Incorrect number of arguments for PROCEDURE test.p13;expected 1, got 0

改爲CALL p13(@a); 即可。

3、[Err] 1414 -OUT or INOUT argument 1 for routine *.* is not a variable or NEWpseudo-variable in BEFORE trigger

此信息也是提示我們傳入的參數不對,*.*的存儲過程參數爲輸出(或輸入)參數,而我們可能傳入相反的參數,例如要求爲輸出參數,而我們傳入的參數非會話變量,即會報此錯。

例:

CALL p13(a); -- 或者CALL p13(0);

提示信息:

[Err] 1414 - OUT or INOUT argument 1 for routine test.p13 is not avariable or NEW pseudo-variable in BEFORE trigger

改正:

CALL p13(@a);

SELECT @a;

 

參考資料:

1、《mysql 5.0存儲過程學習總結》--平凡的世界http://www.ccvita.com/100.html

2、《MYSQL 5.0存儲過程》--Peter Gulutzan 著 陳朋奕 譯

特別申明:學習總結,亦並非什麼優秀學習資料,但轉載請註明原文出處:http://blog.csdn.net/horace20 ^_^

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章