練習7:創建存儲過程和函數

案例:創建一個名稱爲sch的數據表,表結構如表1所示,將表2中的數據插入sch表中。

字段名 數據類型 主鍵 外鍵 非空 唯一 自增
id int(10)
name varchar(50)
glass varchar(50)

表2:

id name glass
1 xiaoming glass1
2 xiaojun glass2

第一步:創建一個sch表,並向sch表中插入表2中的數據,代碼如下:

mysql> create table sch
    -> (
    -> id int(10),
    -> name varchar(50),
    -> glass varchar(50)
    -> );
Query OK, 0 rows affected (0.11 sec)

mysql> insert into sch value(1,'xiaoming','glass 1'),
    -> (2,'xiaojun','glass 2');
Query OK, 2 rows affected (0.05 sec)
Records: 2  Duplicates: 0  Warnings: 0

mysql> desc sch;
+-------+-------------+------+-----+---------+-------+
| Field | Type        | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id    | int(10)     | YES  |     | NULL    |       |
| name  | varchar(50) | YES  |     | NULL    |       |
| glass | varchar(50) | YES  |     | NULL    |       |
+-------+-------------+------+-----+---------+-------+
3 rows in set (0.00 sec)

通過select * from sch來查看插入表格的內容,SQL語句如下:

id name glass
1 xiaoming glass 1
2 xiaojun glass 2

第二步:創建一個存儲函數用來統計表sch中的記錄數。

mysql> create function count_sch()
    -> returns int
    -> return (select count(*) from sch);
Query OK, 0 rows affected (0.05 sec)

mysql> select count_sch();
+-------------+
| count_sch() |
+-------------+
|           2 |
+-------------+
1 row in set (0.00 sec)

創建的存儲函數名稱爲count_sch,通過select count_sch()查看函數執行的情況,這個表中只有兩條記錄,得到的結果也是兩條記錄,說明函數成功執行。

第三步:創建一個存儲過程,通過調用存儲函數的方法來獲取表sch中的記錄數和sch表中id的和。

創建一個存儲過程add_id,同時使用前面創建的存儲函數返回表sch中的記錄數,計算出表中所有的id之和。代碼如下:

mysql> delimiter //
mysql> create procedure add_id(out count int)
    -> begin
    -> declare itmp int;
    -> declare cur_id cursor for select id from sch;
    -> declare exit handler for not found close cur_id;
    -> select count_sch() into count;
    -> set @sum=0;
    -> open cur_id;
    -> repeat
    -> fetch cur_id into itmp;
    -> if itmp<10
    -> then set @sum= @sum+itmp;
    -> end if;
    -> until 0 end repeat;
    -> close cur_id;
    -> end //
Query OK, 0 rows affected (0.06 sec)

mysql> select @a,@sum //
+------+------+
| @a   | @sum |
+------+------+
| NULL | NULL |
+------+------+
1 row in set (0.00 sec)

mysql> delimiter ;

表sch中只有兩條記錄,所有id的和爲3,和預想的執行結果完全相同。這個存儲過程創建了一個cur_id的光標,使用這個光標來獲取每條記錄的id,使用repeat循環語句來實現所有id號相加。


幾個小問題:

1、MySQL存儲過程和存儲函數有什麼區別?

  • 本質上都是存儲程序。函數只能通過return語句返回單個值或表對象;存儲過程不允許執行return,但可以通過out參數返回多個值。
  • 函數限制比較多,不能用臨時表,只能用表變量,還有一些函數都不可用。存儲過程的限制相對就比較少。
  • 函數可以嵌入sql語句中使用,可以在select語句中作爲查詢語句中的一個部分調用,而存儲過程一般是作爲一個獨立的部分來執行。

2.存儲過程中的代碼可以改變嗎?

  • MySQL還不提供對已存在的存儲過程代碼的修改。如果必須修改存儲過程,就必須使用drop語句刪除之後再重新編寫,或者創建一個新的存儲過程。

3.存儲過程中可以調用其他存儲過程嗎?

存儲過程包含用戶定義的sql語句集合,可以使用call語句調用存儲過程,當然在存儲過程中也可以使用call語句調用其他存儲程序,但是不能使用drop語句刪除其他存儲過程。

4.存儲過程的參數不能與數據表中的字段名相同。

在定義存儲過程參數列表時,應注意把參數名與數據庫表中的字段名區別開,否則將出現無法預期的結果。

5.存儲過程的參數可以使用中文嗎?

一般情況下,可能會出現存儲過程中傳入中文參數的情況,例如,某個存儲過程根據用戶的名字查找該用戶的信息,傳入的參數值可能是中文。這時需要在定義存儲過程的時候,在後面加上character set gbk,不然調用存儲過程中使用中文參數會出錯,比如定義userInfo存儲過程,代碼如下:

create procedure useInfo(In u_name varchar(50) character set gbk, out u_age int)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章