MySQL存儲過程php
2018-08-15 23:00:06html
一、存儲過程介紹java
(1) 定義:存儲過程是存儲在數據庫目錄中的一段聲明性SQL語句。 觸發器,其餘存儲過程以及java,python,php等應用程序能夠調用存儲過程。python
遞歸存儲過程:自身的存儲過程。大多數數據庫管理系統支持遞歸存儲過程。 可是,MySQL不支持它。mysql
(2)優勢:sql
1️⃣一般存儲過程有助於提升應用程序的性能。當建立,存儲過程被編譯以後,就存儲在數據庫中。 可是,MySQL實現的存儲過程略有不一樣。 MySQL存儲過程按需編譯。 在編譯存儲過程以後,MySQL將其放入緩存中。 MySQL爲每一個鏈接維護本身的存儲過程高速緩存。 若是應用程序在單個鏈接中屢次使用存儲過程,則使用編譯版本,不然存儲過程的工做方式相似於查詢。chrome
2️⃣存儲過程有助於減小應用程序和數據庫服務器之間的流量,由於應用程序沒必要發送多個冗長的SQL語句,而只能發送存儲過程的名稱和參數。數據庫
3️⃣存儲的程序對任何應用程序都是可重用的和透明的。 存儲過程將數據庫接口暴露給全部應用程序,以便開發人員沒必要開發存儲過程當中已支持的功能。緩存
4️⃣存儲的程序是安全的。 數據庫管理員能夠向訪問數據庫中存儲過程的應用程序授予適當的權限,而不向基礎數據庫表提供任何權限。安全
(3)缺點:
1️⃣若是使用大量存儲過程,那麼使用這些存儲過程的每一個鏈接的內存使用量將會大大增長。 此外,若是您在存儲過程當中過分使用大量邏輯操做,則CPU使用率也會增長,由於數據庫服務器的設計不當於邏輯運算。
2️⃣存儲過程的構造使得開發具備複雜業務邏輯的存儲過程變得更加困難。
3️⃣很難調試存儲過程。
4️⃣開發和維護存儲過程並不容易。
二、存儲過程入門
在Navicat命令行下建立第一個存儲過程HelloProcedure(),也能夠直接使用navicat中的圖形化界面直接建立,也能夠用MySQL Workbench圖形化工具建立。
mysql> delimiter // ---將分隔符;改成// mysql> drop procedure if exists HelloProcedure; ---不要括弧! -> // Query OK, 0 rows affected mysql> create procedure HelloProcedure() -> begin -> select * from products; -> end// Query OK, 0 rows affected mysql> delimiter ; ---將分隔符改回來 mysql> call HelloProcedure(); ---調用存儲過程,要帶括弧!
第一個命令是DELIMITER //
,它與存儲過程語法無關。 DELIMITER
語句將標準分隔符 - 分號(;
)更改成://
。 在這種狀況下,分隔符從分號(;
)更改成雙斜槓//
。
爲何咱們必須更改分隔符? 由於咱們想將存儲過程做爲總體傳遞給服務器,而不是讓mysql工具一次解釋每一個語句。 在END
關鍵字以後,使用分隔符//
來指示存儲過程的結束。 最後一個命令(DELIMITER;
)將分隔符更改回分號(;
)。
三、存儲過程變量
聲明變量: declare x int default 0; declare x, y int default 0; ---能夠同時聲明多個變量 分配變量值: declare total int default 0; set total = 10; ---分配給total的值爲10 declare total int default 0; select count(*) into total from products; ---將sql語句的查詢結果分配給total 變量範圍(做用域): 在存儲過程當中聲明一個變量,那麼當達到存儲過程的END語句時,它將超出範圍,所以在其它代碼塊中沒法訪問。 以@符號開頭的變量是會話變量。直到會話結束前它可用和可訪問。
四、存儲過程參數
參數有三種:
IN
參數時,調用程序必須將參數傳遞給存儲過程。 另外,IN
參數的值被保護。這意味着即便在存儲過程當中更改了IN
參數的值,在存儲過程結束後仍保留其原始值。mysql> drop procedure if exists GetOfficeByCountry; Query OK, 0 rows affected mysql> delimiter // mysql> create procedure GetOfficeByCountry(in countryName varchar(255)) -> begin -> select * -> from offices -> where country = countryName; -> end // Query OK, 0 rows affected mysql> delimiter ; mysql> call GetOfficeByCountry('USA'); +------------+---------------+-----------------+----------------------+--------------+-------+---------+------------+-----------+ | officeCode | city | phone | addressLine1 | addressLine2 | state | country | postalCode | territory | +------------+---------------+-----------------+----------------------+--------------+-------+---------+------------+-----------+ | 1 | San Francisco | +1 650 219 4782 | 100 Market Street | Suite 300 | CA | USA | 94080 | NA | | 2 | Boston | +1 215 837 0825 | 1550 Court Place | Suite 102 | MA | USA | 02107 | NA | | 3 | NYC | +1 212 555 3000 | 523 East 53rd Street | apt. 5A | NY | USA | 10022 | NA | +------------+---------------+-----------------+----------------------+--------------+-------+---------+------------+-----------+ 3 rows in set Query OK, 0 rows affected mysql> drop procedure if exists CountOrderByStatus; Query OK, 0 rows affected
OUT
參數的值,並將其更改後新值傳遞迴調用程序。請注意,存儲過程在啓動時沒法訪問OUT
參數的初始值。mysql> drop procedure if exists CountOrderByStatus; Query OK, 0 rows affected mysql> delimiter // mysql> create procedure CountOrderByStatus(in orderStatus varchar(255),out total int) -> begin -> select count(orderNumber) -> into total -> from orders -> where status = orderStatus; -> end // Query OK, 0 rows affected mysql> delimiter ; mysql> call CountOrderByStatus('Shipped',@total); Query OK, 1 row affected mysql> select @total; +--------+ | @total | +--------+ | 303 | +--------+ 1 row in set
INOUT
參數是IN
和OUT
參數的組合。這意味着調用程序能夠傳遞參數,而且存儲過程能夠修改INOUT
參數並將新值傳遞迴調用程序。mysql> drop procedure if exists set_counter; Query OK, 0 rows affected mysql> delimiter // mysql> create procedure set_counter(inout count int(4),in inc int(4)) -> begin -> set count = count + inc; -> end // Query OK, 0 rows affected mysql> delimiter ; mysql> set @counter = 1; Query OK, 0 rows affected mysql> call set_counter(@counter,1); ---2 Query OK, 0 rows affected mysql> call set_counter(@counter,1); ---3 Query OK, 0 rows affected mysql> call set_counter(@counter,5); ---8 Query OK, 0 rows affected mysql> select @counter; +----------+ | @counter | +----------+ | 8 | +----------+ 1 row in set
五、返回多個值的存儲過程
DELIMITER $$ CREATE PROCEDURE get_order_by_cust( IN cust_no INT, OUT shipped INT, OUT canceled INT, OUT resolved INT, OUT disputed INT) BEGIN -- shipped SELECT count(*) INTO shipped FROM orders WHERE customerNumber = cust_no AND status = 'Shipped'; -- canceled SELECT count(*) INTO canceled FROM orders WHERE customerNumber = cust_no AND status = 'Canceled'; -- resolved SELECT count(*) INTO resolved FROM orders WHERE customerNumber = cust_no AND status = 'Resolved'; -- disputed SELECT count(*) INTO disputed FROM orders WHERE customerNumber = cust_no AND status = 'Disputed'; END
六、IF語句(if then else end if;和 if then elseif then else end if;)
mysql> delimiter // mysql> create procedure GetCustomerLevel(in p_cusNum int(11),out p_cusLevel varchar(10)) -> begin -> declare creditlim double; -> -> select creditlimit into creditlim -> from customers -> where customerNumber = p_cusNum; -> -> if creditlim > 50000 then -> set p_cusLevel = 'PLATINUM'; -> elseif (creditlim <= 50000 and creditlim >= 10000) then -> set p_cusLevel = 'GOLD'; -> elseif creditlim < 10000 then -> set p_cusLevel = 'SILVER'; -> end if; -> end // Query OK, 0 rows affected mysql> call GetCustomerLevel(103,@p_cusLevel); -> // Query OK, 1 row affected mysql> delimiter ; mysql> select @p_cusLevel; +-------------+ | @p_cusLevel | +-------------+ | GOLD | +-------------+ 1 row in set
七、CASE語句
case when ... then ...
when ... then ...
else ...
end case;
注意:在select查詢語句中,能夠直接在end 後面加上字段別名!
case when ... then ...
when ... then ...
else ...
end 字段別名; (或者end as 字段別名)
mysql> delimiter // mysql> create procedure GetCusShipping(in p_cusNum int(11),out p_shipping varchar(50)) -> begin -> declare cusCountry varchar(50); -> -> select country into cusCountry -> from customers -> where customerNumber = p_cusNum; -> -> case cusCountry -> when 'USA' then set p_shipping = '2'; -> when 'Canada' then set p_shipping = '3'; -> else -> set p_shipping = '5'; -> end case; -> end // Query OK, 0 rows affected mysql> delimiter ; mysql> set @p_cusNum = 112; Query OK, 0 rows affected mysql> select country into @country -> from customers -> where customerNumber = @p_cusNum; Query OK, 1 row affected mysql> call GetCusShipping(@p_cusNum,@shipping); Query OK, 1 row affected mysql> select @p_cusNum as Customer, -> @country as Country, -> @shipping as Shipping; +----------+---------+----------+ | Customer | Country | Shipping | +----------+---------+----------+ | 112 | USA | 2 | +----------+---------+----------+ 1 row in set
注意:能夠直接在navicatl裏面建立存儲過程,建立的時候選擇參數類型的時候記得加上具體的範圍,保存的時候只用寫上存儲過程的名稱,不用帶括號。
八、IF和CASE語句使用技巧
IF語句和CASE語句的時候,看我的喜愛。
IF判斷嵌套少的話,使用IF更方便,可是IF判斷嵌套太多的話,建議使用CASE更加簡單易讀!
九、循環
while...do...end while;
begin declare x int; declare str varchar(255); set x = 1; set str = ''; while x <= 5 do set str = concat(str,x,','); set x = x + 1; end while; select str; end
mysql> call test_mysql_while_loop();
+------------+
| str |
+------------+
| 1,2,3,4,5, |
+------------+
1 row in set
Query OK, 0 rows affected
repeat...until...end repeat;
begin declare x int; declare str varchar(255); set x = 1; set str = ''; repeat set str = concat(str,x,','); set x = x + 1; until x > 5 end repeat; select str; end
mysql> call test_mysql_repeat_loop();
+------------+
| str |
+------------+
| 1,2,3,4,5, |
+------------+
1 row in set
Query OK, 0 rows affected
loop...leave...iterate...; leave至關於break,iterate至關於continue.
begin declare x int; declare str varchar(255); set x = 1; set str = ''; loop_label: loop if x > 10 then leave loop_label; end if; set x = x + 1; if(x mod 2) then iterate loop_label; else set str = concat(str,x,','); end if; end loop; select str; end
mysql> call test_mysql_loop();
+-------------+
| str |
+-------------+
| 2,4,6,8,10, |
+-------------+
1 row in set
Query OK, 0 rows affected
十、遊標
要處理存儲過程當中的結果集,請使用遊標。遊標容許您迭代查詢返回的一組行,並相應地處理每行。
MySQL遊標爲只讀(沒法經過光標更新基礎表中的數據),不可滾動(只能按照select語句的順序獲取行)和敏感(敏感指向實際數據,不敏感指向數據副本,敏感比不敏感執行的快)。
BEGIN DECLARE v_finished INTEGER DEFAULT 0; DECLARE v_email varchar(100) DEFAULT ""; -- 1、declare cursor for employee email DEClARE email_cursor CURSOR FOR SELECT email FROM employees; -- 2、declare NOT FOUND handler DECLARE CONTINUE HANDLER FOR NOT FOUND SET v_finished = 1; -- 3、open OPEN email_cursor; get_email: LOOP -- 4、fetch FETCH email_cursor INTO v_email; -- 5、not found IF v_finished = 1 THEN LEAVE get_email; END IF; -- 6、build email list SET email_list = CONCAT(v_email,";",email_list); END LOOP get_email; -- 7、close CLOSE email_cursor; END mysql> set @email_list = ""; Query OK, 0 rows affected mysql> call build_email_list(@email_list); Query OK, 0 rows affected mysql> select @email_list; +-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | @email_list | +-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | mgerard@gmail.com;ykato@gmail.com;mnishi@gmail.com;tking@gmail.com;pmarsh@yiibai.com;afixter@yiibai.com;bjones@gmail.com;lbott@yiibai.com;pcastillo@gmail.com;ghernande@gmail.com;lbondur@yiibai.com;gvanauf@yiibai.com;ftseng@yiibai.com;spatterson@yiibai.com;jfirrelli@yiibai.com;lthompson@yiibai.com;ljennings@yiibai.com;abow@gmail.com;gbondur@gmail.com;wpatterson@yiibai.com;jfirrelli@yiibai.com;mpatterso@yiibai.com;dmurphy@yiibai.com; | +-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 1 row in set
十一、在數據庫中列出存儲過程
mysql> show procedure status;---列出有權訪問的數據庫的全部存儲過程 +----------+--------------------------+-----------+----------------+---------------------+---------------------+---------------+---------+----------------------+----------------------+--------------------+ | Db | Name | Type | Definer | Modified | Created | Security_type | Comment | character_set_client | collation_connection | Database Collation | +----------+--------------------------+-----------+----------------+---------------------+---------------------+---------------+---------+----------------------+----------------------+--------------------+ | mydb2 | GetAllByUsername | PROCEDURE | root@localhost | 2018-08-07 17:06:32 | 2018-08-07 17:06:32 | DEFINER | | utf8 | utf8_general_ci | utf8_general_ci | | mydb2 | GetAllUser | PROCEDURE | root@localhost | 2018-08-06 16:14:26 | 2018-08-06 16:14:26 | DEFINER | | utf8 | utf8_general_ci | utf8_general_ci | | mydb2 | GetAllUser2 | PROCEDURE | root@localhost | 2018-08-06 16:21:29 | 2018-08-06 16:21:29 | DEFINER | | utf8 | utf8_general_ci | utf8_general_ci | | yiibaidb | AddOrderItem | PROCEDURE | root@localhost | 2018-08-08 11:50:42 | 2018-08-08 11:50:42 | DEFINER | | utf8 | utf8_general_ci | utf8_general_ci | | yiibaidb | build_email_list | PROCEDURE | root@localhost | 2018-08-16 10:11:45 | 2018-08-16 10:11:45 | DEFINER | | utf8mb4 | utf8mb4_general_ci | utf8_general_ci | | yiibaidb | CountOrderByStatus | PROCEDURE | root@localhost | 2018-08-07 19:23:47 | 2018-08-07 19:23:47 | DEFINER | | utf8 | utf8_general_ci | utf8_general_ci | | yiibaidb | Divide | PROCEDURE | root@localhost | 2018-08-08 14:30:07 | 2018-08-08 14:30:07 | DEFINER | | utf8 | utf8_general_ci | utf8_general_ci | | yiibaidb | GetCusShipping | PROCEDURE | root@localhost | 2018-08-16 09:20:51 | 2018-08-16 09:20:51 | DEFINER | | utf8mb4 | utf8mb4_general_ci | utf8_general_ci | | yiibaidb | GetCustomerLevel | PROCEDURE | root@localhost | 2018-08-07 22:41:38 | 2018-08-07 22:41:38 | DEFINER | | utf8 | utf8_general_ci | utf8_general_ci | | yiibaidb | GetCustomerLevel2 | PROCEDURE | root@localhost | 2018-08-08 14:57:09 | 2018-08-08 14:57:09 | DEFINER | | utf8 | utf8_general_ci | utf8_general_ci | | yiibaidb | GetCustomerShipping | PROCEDURE | root@localhost | 2018-08-07 22:57:06 | 2018-08-07 22:57:06 | DEFINER | | utf8 | utf8_general_ci | utf8_general_ci | | yiibaidb | GetOfficeByCountry | PROCEDURE | root@localhost | 2018-08-07 19:02:53 | 2018-08-07 19:02:53 | DEFINER | | utf8 | utf8_general_ci | utf8_general_ci | | yiibaidb | get_order_by_cust | PROCEDURE | root@localhost | 2018-08-07 19:58:27 | 2018-08-07 19:58:27 | DEFINER | | utf8 | utf8_general_ci | utf8_general_ci | | yiibaidb | HelloProcedure | PROCEDURE | root@localhost | 2018-08-15 19:20:34 | 2018-08-15 19:20:34 | DEFINER | | utf8mb4 | utf8mb4_general_ci | utf8_general_ci | | yiibaidb | insert_article_tags | PROCEDURE | root@localhost | 2018-08-08 10:57:53 | 2018-08-08 10:57:53 | DEFINER | | utf8 | utf8_general_ci | utf8_general_ci | | yiibaidb | insert_article_tags_exit | PROCEDURE | root@localhost | 2018-08-08 11:12:57 | 2018-08-08 11:12:57 | DEFINER | | utf8 | utf8_general_ci | utf8_general_ci | | yiibaidb | set_counter | PROCEDURE | root@localhost | 2018-08-07 19:31:14 | 2018-08-07 19:31:14 | DEFINER | | utf8 | utf8_general_ci | utf8_general_ci | | yiibaidb | test_mysql_loop | PROCEDURE | root@localhost | 2018-08-16 09:39:36 | 2018-08-16 09:39:36 | DEFINER | | utf8mb4 | utf8mb4_general_ci | utf8_general_ci | | yiibaidb | test_mysql_repeat_loop | PROCEDURE | root@localhost | 2018-08-16 09:38:14 | 2018-08-16 09:38:14 | DEFINER | | utf8mb4 | utf8mb4_general_ci | utf8_general_ci | | yiibaidb | test_mysql_while_loop | PROCEDURE | root@localhost | 2018-08-16 09:33:52 | 2018-08-16 09:33:52 | DEFINER | | utf8mb4 | utf8mb4_general_ci | utf8_general_ci | +----------+--------------------------+-----------+----------------+---------------------+---------------------+---------------+---------+----------------------+----------------------+--------------------+ 20 rows in set mysql> show procedure status where db = 'yiibaidb';---列出指定數據庫的全部存儲過程 +----------+--------------------------+-----------+----------------+---------------------+---------------------+---------------+---------+----------------------+----------------------+--------------------+ | Db | Name | Type | Definer | Modified | Created | Security_type | Comment | character_set_client | collation_connection | Database Collation | +----------+--------------------------+-----------+----------------+---------------------+---------------------+---------------+---------+----------------------+----------------------+--------------------+ | yiibaidb | AddOrderItem | PROCEDURE | root@localhost | 2018-08-08 11:50:42 | 2018-08-08 11:50:42 | DEFINER | | utf8 | utf8_general_ci | utf8_general_ci | | yiibaidb | build_email_list | PROCEDURE | root@localhost | 2018-08-16 10:11:45 | 2018-08-16 10:11:45 | DEFINER | | utf8mb4 | utf8mb4_general_ci | utf8_general_ci | | yiibaidb | CountOrderByStatus | PROCEDURE | root@localhost | 2018-08-07 19:23:47 | 2018-08-07 19:23:47 | DEFINER | | utf8 | utf8_general_ci | utf8_general_ci | | yiibaidb | Divide | PROCEDURE | root@localhost | 2018-08-08 14:30:07 | 2018-08-08 14:30:07 | DEFINER | | utf8 | utf8_general_ci | utf8_general_ci | | yiibaidb | GetCusShipping | PROCEDURE | root@localhost | 2018-08-16 09:20:51 | 2018-08-16 09:20:51 | DEFINER | | utf8mb4 | utf8mb4_general_ci | utf8_general_ci | | yiibaidb | GetCustomerLevel | PROCEDURE | root@localhost | 2018-08-07 22:41:38 | 2018-08-07 22:41:38 | DEFINER | | utf8 | utf8_general_ci | utf8_general_ci | | yiibaidb | GetCustomerLevel2 | PROCEDURE | root@localhost | 2018-08-08 14:57:09 | 2018-08-08 14:57:09 | DEFINER | | utf8 | utf8_general_ci | utf8_general_ci | | yiibaidb | GetCustomerShipping | PROCEDURE | root@localhost | 2018-08-07 22:57:06 | 2018-08-07 22:57:06 | DEFINER | | utf8 | utf8_general_ci | utf8_general_ci | | yiibaidb | GetOfficeByCountry | PROCEDURE | root@localhost | 2018-08-07 19:02:53 | 2018-08-07 19:02:53 | DEFINER | | utf8 | utf8_general_ci | utf8_general_ci | | yiibaidb | get_order_by_cust | PROCEDURE | root@localhost | 2018-08-07 19:58:27 | 2018-08-07 19:58:27 | DEFINER | | utf8 | utf8_general_ci | utf8_general_ci | | yiibaidb | HelloProcedure | PROCEDURE | root@localhost | 2018-08-15 19:20:34 | 2018-08-15 19:20:34 | DEFINER | | utf8mb4 | utf8mb4_general_ci | utf8_general_ci | | yiibaidb | insert_article_tags | PROCEDURE | root@localhost | 2018-08-08 10:57:53 | 2018-08-08 10:57:53 | DEFINER | | utf8 | utf8_general_ci | utf8_general_ci | | yiibaidb | insert_article_tags_exit | PROCEDURE | root@localhost | 2018-08-08 11:12:57 | 2018-08-08 11:12:57 | DEFINER | | utf8 | utf8_general_ci | utf8_general_ci | | yiibaidb | set_counter | PROCEDURE | root@localhost | 2018-08-07 19:31:14 | 2018-08-07 19:31:14 | DEFINER | | utf8 | utf8_general_ci | utf8_general_ci | | yiibaidb | test_mysql_loop | PROCEDURE | root@localhost | 2018-08-16 09:39:36 | 2018-08-16 09:39:36 | DEFINER | | utf8mb4 | utf8mb4_general_ci | utf8_general_ci | | yiibaidb | test_mysql_repeat_loop | PROCEDURE | root@localhost | 2018-08-16 09:38:14 | 2018-08-16 09:38:14 | DEFINER | | utf8mb4 | utf8mb4_general_ci | utf8_general_ci | | yiibaidb | test_mysql_while_loop | PROCEDURE | root@localhost | 2018-08-16 09:33:52 | 2018-08-16 09:33:52 | DEFINER | | utf8mb4 | utf8mb4_general_ci | utf8_general_ci | +----------+--------------------------+-----------+----------------+---------------------+---------------------+---------------+---------+----------------------+----------------------+--------------------+ 17 rows in set mysql> show procedure status where name like '%product%'; Empty set mysql> show procedure status where name like '%email%';---列出指定名稱的存儲過程 +----------+------------------+-----------+----------------+---------------------+---------------------+---------------+---------+----------------------+----------------------+--------------------+ | Db | Name | Type | Definer | Modified | Created | Security_type | Comment | character_set_client | collation_connection | Database Collation | +----------+------------------+-----------+----------------+---------------------+---------------------+---------------+---------+----------------------+----------------------+--------------------+ | yiibaidb | build_email_list | PROCEDURE | root@localhost | 2018-08-16 10:11:45 | 2018-08-16 10:11:45 | DEFINER | | utf8mb4 | utf8mb4_general_ci | utf8_general_ci | +----------+------------------+-----------+----------------+---------------------+---------------------+---------------+---------+----------------------+----------------------+--------------------+ 1 row in set mysql> show create procedure build_email_list;---列出存儲過程的源代碼 +------------------+----------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------+----------------------+--------------------+ | Procedure | sql_mode | Create Procedure | character_set_client | collation_connection | Database Collation | +------------------+----------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------+----------------------+--------------------+ | build_email_list | STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION | CREATE DEFINER=`root`@`localhost` PROCEDURE `build_email_list`(INOUT email_list varchar(4000)) BEGIN DECLARE v_finished INTEGER DEFAULT 0; DECLARE v_email varchar(100) DEFAULT ""; -- 1、declare cursor for employee email DEClARE email_cursor CURSOR FOR SELECT email FROM employees; -- 2、declare NOT FOUND handler DECLARE CONTINUE HANDLER FOR NOT FOUND SET v_finished = 1; -- 3、open OPEN email_cursor; get_email: LOOP -- 4、fetch FETCH email_cursor INTO v_email; -- 5、not found IF v_finished = 1 THEN LEAVE get_email; END IF; -- 6、build email list SET email_list = CONCAT(v_email,";",email_list); END LOOP get_email; -- 7、close CLOSE email_cursor; END | utf8mb4 | utf8mb4_general_ci | utf8_general_ci | +------------------+----------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------+----------------------+--------------------+ 1 row in set
十二、存儲過程當中的MySQL錯誤處理
BEGIN #Routine body goes here... DECLARE EXIT HANDLER FOR 1062 SELECT 'Duplicate keys error encountered'; DECLARE EXIT HANDLER FOR SQLEXCEPTION SELECT 'SQLException encountered'; DECLARE EXIT HANDLER FOR SQLSTATE '23000' SELECT 'SQLSTATE 23000'; INSERT INTO article_tags(article_id,tag_id) VALUES(article_id,tag_id); SELECT COUNT(*) FROM article_tags; END
插入重複的值得時候會報錯!處理程序優先級:每個mysql錯誤都對應一個錯誤代碼(例如1062),因此處理錯誤優先級是錯誤越具體,優先級越高。
mysql> call insert_article_tags_3(1,3);
+----------------------------------+
| Duplicate keys error encountered |
+----------------------------------+
| Duplicate keys error encountered |
+----------------------------------+
1 row in set
Query OK, 0 rows affected
使用命名錯誤條件:
也就是給錯誤代碼1051取個好理解的名字,這樣發生對應的錯誤的時候,知道具體是什麼錯誤。
DECLARE table_not_found CONDITION for 1051; DECLARE EXIT HANDLER FOR table_not_found SELECT 'Please create table abc first'; SELECT * FROM abc;
1三、使用MySQL SIGNAL/RESIGNAL語句引起錯誤條件
DELIMITER $$ CREATE PROCEDURE AddOrderItem(in orderNo int, in productCode varchar(45), in qty int,in price double, in lineNo int ) BEGIN DECLARE C INT; SELECT COUNT(orderNumber) INTO C FROM orders WHERE orderNumber = orderNo; -- check if orderNumber exists IF(C != 1) THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Order No not found in orders table'; END IF; -- more code below -- ... END $$ DELIMITER ;
DELIMITER $$ CREATE PROCEDURE Divide(IN numerator INT, IN denominator INT, OUT result double) BEGIN DECLARE division_by_zero CONDITION FOR SQLSTATE '22012'; DECLARE CONTINUE HANDLER FOR division_by_zero RESIGNAL SET MESSAGE_TEXT = 'Division by zero / Denominator cannot be zero'; -- IF denominator = 0 THEN SIGNAL division_by_zero; ELSE SET result := numerator / denominator; END IF; END $$ DELIMITER ;
1四、存儲函數
存儲的函數是返回單個值的特殊類型的存儲程序。您使用存儲的函數來封裝在SQL語句或存儲的程序中可重用的經常使用公式或業務規則。
能夠在sql語句中和存儲過程當中調用存儲函數,這樣有助於代碼的可讀性和可維護性。
BEGIN DECLARE lvl varchar(10); IF p_creditLimit > 50000 THEN SET lvl = 'PLATINUM'; ELSEIF (p_creditLimit <= 50000 AND p_creditLimit >= 10000) THEN SET lvl = 'GOLD'; ELSEIF p_creditLimit < 10000 THEN SET lvl = 'SILVER'; END IF; RETURN (lvl); END
mysql> select customerName,CustomerLevel(creditLimit) -> from customers -> order by customerName; +------------------------------------+----------------------------+ | customerName | CustomerLevel(creditLimit) | +------------------------------------+----------------------------+ | Alpha Cognac | PLATINUM | | American Souvenirs Inc | SILVER | | Amica Models & Co. | PLATINUM | | ANG Resellers | SILVER | | Anna's Decorations, Ltd | PLATINUM | | Anton Designs, Ltd. | SILVER | | Asian Shopping Network, Co | SILVER | | Asian Treasures, Inc. | SILVER | | Atelier graphique | GOLD | | Australian Collectables, Ltd | PLATINUM | | Australian Collectors, Co. | PLATINUM | | Australian Gift Network, Co | PLATINUM | | Auto Associs & Cie. | PLATINUM | | Auto Canal+ Petit | PLATINUM | | Auto-Moto Classics Inc. | GOLD | | AV Stores, Co. | PLATINUM | | Baane Mini Imports | PLATINUM | | Bavarian Collectables Imports, Co. | PLATINUM | | BG&E Collectables | SILVER | | Blauer See Auto, Co. | PLATINUM | | Boards & Toys Co. | GOLD | | CAF Imports | PLATINUM | | Cambridge Collectables Co. | GOLD | | Canadian Gift Exchange Network | PLATINUM | | Classic Gift Ideas, Inc | PLATINUM | | Classic Legends Inc. | PLATINUM | | Clover Collections, Co. | PLATINUM | | Collectable Mini Designs Co. | PLATINUM | | Collectables For Less Inc. | PLATINUM | | Corporate Gift Ideas Co. | PLATINUM | | Corrida Auto Replicas, Ltd | PLATINUM | | Cramer Spezialitten, Ltd | SILVER | | Cruz & Sons Co. | PLATINUM | | Daedalus Designs Imports | PLATINUM | | Danish Wholesale Imports | PLATINUM | | Der Hund Imports | SILVER | | Diecast Classics Inc. | PLATINUM | | Diecast Collectables | PLATINUM | | Double Decker Gift Stores, Ltd | GOLD | | Down Under Souveniers, Inc | PLATINUM | | Dragon Souveniers, Ltd. | PLATINUM | | Enaco Distributors | PLATINUM | | Euro+ Shopping Channel | PLATINUM | | Extreme Desk Decorations, Ltd | PLATINUM | | Feuer Online Stores, Inc | SILVER | | Franken Gifts, Co | SILVER | | Frau da Collezione | GOLD | | FunGiftIdeas.com | PLATINUM | | Gift Depot Inc. | PLATINUM | | Gift Ideas Corp. | GOLD | | Gifts4AllAges.com | GOLD | | giftsbymail.co.uk | PLATINUM | | GiftsForHim.com | PLATINUM | | Handji Gifts& Co | PLATINUM | | Havel & Zbyszek Co | SILVER | | Heintze Collectables | PLATINUM | | Herkku Gifts | PLATINUM | | Iberia Gift Imports, Corp. | PLATINUM | | Kelly's Gift Shop | PLATINUM | | King Kong Collectables, Co. | PLATINUM | | Kommission Auto | SILVER | | Kremlin Collectables, Co. | SILVER | | L'ordine Souveniers | PLATINUM | | La Corne D'abondance, Co. | PLATINUM | | La Rochelle Gifts | PLATINUM | | Land of Toys Inc. | PLATINUM | | Lisboa Souveniers, Inc | SILVER | | Lyon Souveniers | PLATINUM | | Marseille Mini Autos | PLATINUM | | Marta's Replicas Co. | PLATINUM | | Men 'R' US Retailers, Ltd. | PLATINUM | | Messner Shopping Network | SILVER | | Microscale Inc. | GOLD | | Mini Auto Werke | GOLD | | Mini Caravy | PLATINUM | | Mini Classics | PLATINUM | | Mini Creations Ltd. | PLATINUM | | Mini Gifts Distributors Ltd. | PLATINUM | | Mini Wheels Co. | PLATINUM | | Mit Vergngen & Co. | SILVER | | Motor Mint Distributors Inc. | PLATINUM | | Muscle Machine Inc | PLATINUM | | Natrlich Autos | SILVER | | Norway Gifts By Mail, Co. | PLATINUM | | Online Diecast Creations Co. | PLATINUM | | Online Mini Collectables | PLATINUM | | Osaka Souveniers Co. | PLATINUM | | Oulu Toy Supplies, Inc. | PLATINUM | | Petit Auto | PLATINUM | | Porto Imports Co. | SILVER | | Precious Collectables | SILVER | | Qubec Home Shopping Network | GOLD | | Raanan Stores, Inc | SILVER | | Reims Collectables | PLATINUM | | Rovelli Gifts | PLATINUM | | Royal Canadian Collectables, Ltd. | PLATINUM | | Royale Belge | GOLD | | Salzburg Collectables | PLATINUM | | SAR Distributors, Co | SILVER | | Saveley & Henriot, Co. | PLATINUM | | Scandinavian Gift Ideas | PLATINUM | | Schuyler Imports | SILVER | | Signal Collectibles Ltd. | PLATINUM | | Signal Gift Stores | PLATINUM | | Souveniers And Things Co. | PLATINUM | | Stuttgart Collectable Exchange | SILVER | | Stylish Desk Decors, Co. | PLATINUM | | Suominen Souveniers | PLATINUM | | Super Scale Inc. | PLATINUM | | Technics Stores Inc. | PLATINUM | | Tekni Collectables Inc. | GOLD | | The Sharp Gifts Warehouse | PLATINUM | | Tokyo Collectables, Ltd | PLATINUM | | Toms Spezialitten, Ltd | PLATINUM | | Toys of Finland, Co. | PLATINUM | | Toys4GrownUps.com | PLATINUM | | UK Collectables, Ltd. | PLATINUM | | Vida Sport, Ltd | PLATINUM | | Vitachrome Inc. | PLATINUM | | Volvo Model Replicas, Co | PLATINUM | | Warburg Exchange | SILVER | | West Coast Collectables Co. | PLATINUM | +------------------------------------+----------------------------+ 122 rows in set