![](/img/trans.png)
[英]How to use a mysql stored procedure result set in another stored procedure
[英]Mysql Stored Procedure: how to handle empty result set
我編寫了一個程序,其中一個語句沒有正確執行:
SELECT thumb_image into v_thumb_image FROM RESTAURANT_IMAGE WHERE
RESTAURANT_ID = v_restaurant_id
我調查的原因是,如果在任何時候結果集為空,則程序不會進一步運行語句。
請注意,我在一個循環中調用它。
我關心的是如果對於任何v_restaurant_id
,結果集為空,則不會停止執行。
完整程序:
-- --------------------------------------------------------------------------------
-- Routine DDL
-- Note: comments before and after the routine body will not be stored by the server
-- --------------------------------------------------------------------------------
DELIMITER $$
CREATE DEFINER=`root`@`localhost` PROCEDURE `populate_restaurant_details`()
BEGIN
DECLARE v_finished_cuisines,
v_finished,
v_restaurant_id,
v_count_discount
INT DEFAULT 0;
DECLARE v_cuisines,
v_thumb_image
varchar(200) DEFAULT "";
DECLARE cuisine_title varchar(50) DEFAULT "";
-- Fetch all restaurant id
DECLARE restaurant_cursor CURSOR FOR
SELECT id FROM delhifoodonline.restaurant order by id desc;
DECLARE CONTINUE HANDLER
FOR NOT FOUND SET v_finished = 1;
OPEN restaurant_cursor;
get_restaurant: LOOP
FETCH restaurant_cursor INTO v_restaurant_id;
IF v_finished = 1 THEN
LEAVE get_restaurant;
END IF;
SET v_finished_cuisines ="";
SET v_thumb_image = "";
begin
DECLARE CONTINUE HANDLER FOR NOT FOUND SET v_thumb_image = NULL;
SELECT thumb_image into v_thumb_image
FROM restaurant_image
WHERE restaurant_id = v_restaurant_id
ORDER BY id
LIMIT 1;
end;
SELECT count(*) into v_count_discount FROM restaurant_discount WHERE
restaurant_id = v_restaurant_id;
BLOCK2: BEGIN
DECLARE cuisines_cursor CURSOR FOR
SELECT cuisine.title FROM restaurant_cuisine INNER JOIN cuisine
ON restaurant_cuisine.cuisine_id = cuisine.id
WHERE
restaurant_cuisine.restaurant_id = v_restaurant_id
LIMIT 0,5;
DECLARE CONTINUE HANDLER
FOR NOT FOUND SET v_finished_cuisines = 1;
SET v_cuisines = "";
OPEN cuisines_cursor;
get_cuisine: LOOP
FETCH cuisines_cursor INTO cuisine_title;
IF v_finished_cuisines = 1 THEN
LEAVE get_cuisine;
END IF;
SET v_cuisines = CONCAT(cuisine_title,", ",v_cuisines);
END LOOP get_cuisine;
CLOSE cuisines_cursor;
END BLOCK2;
SET v_cuisines = TRIM(BOTH ", " FROM v_cuisines);
IF v_count_discount > 0 THEN
SET v_count_discount = 1;
ELSE
SET v_count_discount = 0;
END IF;
UPDATE restaurant SET
thumb_image = v_thumb_image,
cuisines_list = v_cuisines,
discount_available = v_count_discount
WHERE id= v_restaurant_id;
END LOOP get_restaurant;
CLOSE restaurant_cursor;
END
從文檔 :
NOT FOUND是以'02'開頭的SQLSTATE值類的簡寫。 這與游標的上下文相關,用於控制光標到達數據集末尾時發生的情況。 如果沒有更多行可用,則SQLSTATE值為“02000”時會出現“無數據”條件。 要檢測此情況,可以為其設置處理程序(或對於NOT FOUND條件)。 有關示例,請參見第13.6.6節“游標”。 對於不檢索任何行的SELECT ... INTO var_list語句,也會出現這種情況。
因此,當restaurant_image
表中沒有返回任何行時,它也會遇到NOT FOUND
狀態,並調用定義的處理程序,這會導致離開循環。
一種解決方案是通過將其放在BEGIN...END
塊中來為該選擇聲明另一個處理程序:
begin
DECLARE CONTINUE HANDLER FOR NOT FOUND SET v_thumb_image = NULL;
SELECT thumb_image into v_thumb_image
FROM restaurant_image
WHERE restaurant_id = v_restaurant_id
ORDER BY id
LIMIT 1;
end;
畢竟,為什么使用存儲過程和游標這樣做會很慢。 您可以實現執行單個語句的相同功能:
UPDATE restaurant
SET thumb_image = (
SELECT thumb_image
FROM restaurant_image
WHERE restaurant_id = restaurant.id
ORDER BY id
LIMIT 1),
discount_available = IF(EXISTS(
SELECT 1
FROM restaurant_discount
WHERE restaurant_id = restaurant.id), 1, 0),
cuisines_list = (
SELECT group_concat(cuisine.title separator ', ')
FROM restaurant_cuisine
INNER JOIN cuisine ON restaurant_cuisine.cuisine_id = cuisine.id
WHERE restaurant_cuisine.restaurant_id = restaurant.id
LIMIT 0,5)
或者通過消除每行的子查詢使其更快:
UPDATE restaurant r
LEFT JOIN
(SELECT restaurant_id, count(*) AS discount_available
FROM restaurant_discount
GROUP BY restaurant_id) d ON r.id = d.restaurant_id
LEFT JOIN
(SELECT restaurant_id, thumb_image
FROM restaurant_image r1
WHERE NOT EXISTS (
SELECT 1 FROM restaurant_image r2 WHERE r2.restaurant_id = r1.restaurant_id AND r2.id < r1.id
)) t ON r.id = t.restaurant_id
LEFT JOIN
(SELECT rc.restaurant_id, SUBSTRING_INDEX(GROUP_CONCAT(c.title SEPARATOR ', '), ',', 5) AS cuisines_list
FROM restaurant_cuisine rc
INNER JOIN cuisine c ON rc.cuisine_id = c.id
GROUP BY rc.restaurant_id
) rc ON r.id = rc.restaurant_id
SET r.discount_available = IF(d.discount_available = 0, 0, 1),
r.thumb_image = t.thumb_image,
r.cuisines_list = rc.cuisines_list
分別嘗試這些子查詢以找到更好的理解。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.