MySQL創建存儲過程
MySQL中,創建存儲過程的基本形式如下:
CREATE PROCEDURE sp_name ([proc_parameter[,...]])
[characteristic ...] routine_body
其中,sp_name參數是存儲過程的名稱;proc_parameter表示存儲過程的參數列表; characteristic參數指定存儲過程的特性;routine_body參數是SQL代碼的內容,可以用BEGIN…END來標志SQL代碼的開始和結束。
-
proc_parameter
proc_parameter中的每個參數由3部分組成。這3部分分別是輸入輸出類型、參數名稱和參數類型。其形式如下:
[ IN | OUT | INOUT ] param_name type
其中,IN表示輸入參數;OUT表示輸出參數; INOUT表示既可以是輸入,也可以是輸出; param_name參數是存儲過程的參數名稱;type參數指定存儲過程的參數類型,該類型可以是MySQL數據庫的任意數據類型。
-
characteristic
characteristic參數有多個取值。其取值說明如下:
- LANGUAGE SQL:說明routine_body部分是由SQL語言的語句組成,這也是數據庫系統默認的語言。
- [NOT] DETERMINISTIC:指明存儲過程的執行結果是否是確定的。DETERMINISTIC表示結果是確定的。每次執行存儲過程時,相同的輸入會得到相同的輸出。NOT DETERMINISTIC表示結果是非確定的,相同的輸入可能得到不同的輸出。默認情況下,結果是非確定的。
- { CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA }:指明子程序使用SQL語句的限制。CONTAINS SQL表示子程序包含SQL語句,但不包含讀或寫數據的語句;NO SQL表示子程序中不包含SQL語句;READS SQL DATA表示子程序中包含讀數據的語句;MODIFIES SQL DATA表示子程序中包含寫數據的語句。默認情況下,系統會指定為CONTAINS SQL。
- SQL SECURITY { DEFINER | INVOKER }:指明誰有權限來執行。DEFINER表示只有定義者自己才能夠執行;INVOKER表示調用者可以執行。默認情況下,系統指定的權限是DEFINER。
- COMMENT 'string':注釋信息。
【示例14-1】 下面創建一個名為num_from_employee的存儲過程。代碼如下:
DROP PROCEDURE IF EXISTS num_from_employee ; DELIMITER // CREATE PROCEDURE num_from_employee ( IN emp_id INT, OUT count_num INT ) READS SQL DATA BEGIN SELECT COUNT(*) INTO count_num FROM employee WHERE d_id=emp_id ; END // DELIMITER ;
說明:MySQL中默認的語句結束符為分號(;)。存儲過程中的SQL語句需要分號來結束。為了避免沖突,首先用"DELIMITER //"將MySQL的結束符設置為//。最后再用"DELIMITER ;"來將結束符恢復成分號。這與創建觸發器時是一樣的。
MySQL創建存儲函數
在MySQL中,創建存儲函數的基本形式如下:
CREATE FUNCTION sp_name ([func_parameter[,...]])
RETURNS type
[characteristic ...] routine_body
其中,sp_name參數是存儲函數的名稱;func_parameter表示存儲函數的參數列表;RETURNS type指定返回值的類型;characteristic參數指定存儲函數的特性,該參數的取值與存儲過程中的取值是一樣的;routine_body參數是SQL代碼的內容,可以用BEGIN…END來標志SQL代碼的開始和結束。
func_parameter
func_parameter可以由多個參數組成,其中每個參數由參數名稱和參數類型組成,其形式如下:param_name type
其中,param_name參數是存儲函數的參數名稱;type參數指定存儲函數的參數類型,該類型可以是MySQL數據庫的任意數據類型。
【示例14-2】 下面創建一個名為name_from_employee的存儲函數。代碼如下:
DELIMITER //
CREATE FUNCTION name_from_employee (emp_id INT ) RETURNS VARCHAR(20) BEGIN RETURN (SELECT name FROM employee WHERE num=emp_id ); END //
DELIMITER ;
MySQL臨時表
首先,臨時表只在當前連接可見,當關閉連接時,Mysql會自動刪除表並釋放所有空間。因此在不同的連接中可以創建同名的臨時表,並且操作屬於本連接的臨時表。
創建臨時表的語法與創建表語法類似,不同之處是增加關鍵字TEMPORARY,如:
CREATE TEMPORARY TABLE 表名 (…. )
臨時表使用有一些限制條件:
* 臨時表在 memory、myisam、merge或者innodb上使用,並且不支持mysql cluster簇);
show tables語句不會列出臨時表,在information_schema中也不存在臨時表信息;show create table可以查看臨時表;
* 不能使用rename來重命名臨時表。但是可以alter table rename代替:
mysql>ALTER TABLE orig_name RENAME new_name;
* 可以復制臨時表得到一個新的臨時表,如:
mysql>create temporary table new_table select * from old_table;
* 但在同一個query語句中,相同的臨時表只能出現一次。如:
可以使用:mysql> select * from temp_tb;
但不能使用:mysql> select * from temp_tb, temp_tb as t;
錯誤信息: ERROR 1137 (HY000): Can't reopen table: 'temp_tb'
同樣相同臨時表不能在存儲函數中出現多次,如果在一個存儲函數里,用不同的別名查找一個臨時表多次,或者在這個存儲函數里用不同的語句查找,都會出現這個錯誤。
* 但不同的臨時表可以出現在同一個query語句中,如臨時表temp_tb1, temp_tb2:
Mysql> select * from temp_tb1, temp_tb2;
* 臨時表可以手動刪除:
DROP TEMPORARY TABLE IF EXISTS temp_tb;
在創建臨時表時聲明類型為HEAP,則Mysql會在內存中創建該臨時表,即內存表:如:
CREATE TEMPORARY TABLE 表名 (。。。。) TYPE = HEAP
因為HEAP表存儲在內存中,你對它運行的查詢可能比磁盤上的臨時表快些。如:
mysql> create temporary table temp_tb type='heap' select * from temptb;
CREATE TEMPORARY TABLE `temp_tb` ( `id` int(10) unsigned NOT NULL DEFAULT '0', `Name` char(20) NOT NULL, `Age` tinyint(4) NOT NULL ) ENGINE=MEMORY DEFAULT CHARSET=gbk
臨時表和內存表
臨時表主要是為了放一些中間大結果集的一些子集,內存表可以放一些經常頻繁使用的數據。
* 臨時表:表建在內存里,數據在內存里
* 內存表:表建在磁盤里,數據在內存里
臨時表和內存表所使用內存大小可以通過My.cnf中的max_heap_table_size、tmp_table_size指定:
[mysqld]
max_heap_table_size=1024M #內存表容量
tmp_table_size=1024M #臨時表容量
當數據超過臨時表的最大值設定時,自動轉為磁盤表,此時因需要進行IO操作,性能會大大下降,而內存表不會,內存表滿后,則會提示數據滿錯誤。
show tables 命令不會顯示臨時表。
以下是對內存表和臨時表之間區別的總結:
內存表:
1.缺省存儲引擎為MEMORY
2.可以通過參數max_heap_table_size來設定內存表大小
3.到達max_heap_table_size設定的內存上限后將報錯
4.表定義保存在磁盤上,數據和索引保存在內存中
5.不能包含TEXT、BLOB等字段
臨時表:
1.缺省存儲引擎為MySQL服務器默認引擎,引擎類型只能是:memory(heap)、myisam、merge、innodb(memory臨時表由於表的增大可能會轉變為myisam臨時表)
2.可以通過參數 tmp_table_size 來設定臨時表大小。
3.到達tmp_table_size設定的內存上限后將在磁盤上創建臨時文件
4.表定義和數據都保存在內存中
5.可以包含TEXT, BLOB等字段
臨時表一般比較少用,通常是在應用程序中動態創建或者由MySQL內部根據SQL執行計划需要自己創建。
內存表則大多作為Cache來使用,特別在沒有第三方cache使用時。如今隨着memcache、NoSQL的流行,越來越少選擇使用內存表。