案例:創建一個名稱爲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)