我在这里尝试实现下面的存储过程。但值(value)并没有像预期的那样节省
DELIMITER $$
USE `someDB`$$
DROP PROCEDURE IF EXISTS `AAB`$$
CREATE PROCEDURE `AAB`(IN `feed_setting_user_id` BIGINT)
BEGIN
DECLARE v_friendID, FoFID BIGINT; # use datatype which is used for u.ID used int based on ur result
DECLARE exit_loop, exit_loop1 BOOLEAN DEFAULT FALSE;
DECLARE friend_cursor CURSOR FOR
SELECT `u`.`ID` FROM `users` `u`
WHERE `u`.`ID` IN (SELECT `u1`.`ID` FROM users `u1`
WHERE `u1`.`ID` IN (SELECT `uf`.`friendid` FROM user_friends `uf` WHERE `uf`.`status` = '2' AND `uf`.`userid` = feed_setting_user_id )
OR `u1`.`ID` IN (SELECT `uf2`.`userid` FROM `user_friends` `uf2` WHERE `uf2`.`status` = '2' AND `uf2`.`friendid` = feed_setting_user_id)
AND `u1`.`ID` != feed_setting_user_id);
DECLARE CONTINUE HANDLER FOR NOT FOUND SET exit_loop = TRUE;
DROP TEMPORARY TABLE IF EXISTS unique_tbl; #precaution: when sp stops with error
CREATE TEMPORARY TABLE unique_tbl (user_id BIGINT UNIQUE); #to avoid duplicate added unique
INSERT INTO unique_tbl VALUES (feed_setting_user_id); # added input from sp
OPEN friend_cursor;
friend_loop: LOOP
FETCH friend_cursor INTO v_friendID;
IF exit_loop THEN
LEAVE friend_loop;
ELSE
REPLACE INTO unique_tbl VALUES (v_friendID); # since we need all unique id's using replace if exists
fof: BEGIN
DECLARE friend_of_friend_cursor CURSOR FOR
SELECT `u`.`ID` FROM `users` `u` WHERE `u`.`ID` NOT IN (feed_setting_user_id) AND `u`.`ID`
IN (SELECT `u1`.`ID` FROM `users` `u1`
WHERE `u1`.`ID` IN (SELECT `uf`.`friendid` FROM `user_friends` `uf` WHERE `uf`.`status` = '2' AND `uf`.`userid` = v_friendID AND `uf`.`friendid` != v_friendID)
OR `u1`.`ID` IN (SELECT `uf2`.`userid` FROM `user_friends` `uf2` WHERE `uf2`.`status` = '2' AND `uf2`.`friendid` = v_friendID AND `uf2`.`userid` != v_friendID)
AND `u1`.`ID` != v_friendID );
DECLARE CONTINUE HANDLER FOR NOT FOUND SET exit_loop1 = TRUE;
OPEN friend_of_friend_cursor;
friend_of_friend_loop: LOOP
FETCH friend_of_friend_cursor INTO FoFID;
IF exit_loop1 THEN
LEAVE friend_of_friend_loop;
END IF;
REPLACE INTO unique_tbl VALUES (FoFID);
END LOOP friend_of_friend_loop;
CLOSE friend_of_friend_cursor;
END;
END IF;
END LOOP friend_loop;
CLOSE friend_cursor;
SELECT GROUP_CONCAT(user_id) FROM unique_tbl; #this will show result in comma seperated 2,34,56,78
#cleanup
DROP TEMPORARY TABLE IF EXISTS unique_tbl;
END$$
DELIMITER ;
实际结果:
+-----------------------------------+
| GROUP_CONCAT(user_id) |
+-----------------------------------+
| 1,2,3,5,6,7,8,9,11,14,15,19,20,26 |
+-----------------------------------+
1 row in set (0,01 sec)
Query OK, 0 rows affected (0,01 sec)
预期结果:
+--------------------------------------+
| GROUP_CONCAT(user_id) |
+--------------------------------------+
| 1,2,3,5,6,7,8,9,11,14,15,19,20,25,26 |
+--------------------------------------+
1 row in set (0,01 sec)
Query OK, 0 rows affected (0,01 sec)
ID = 25
已被关闭
调试以上两条SQL:
将 feed_setting_user_id = 15
设置为以下 SQL 查询
SELECT
`u`.`ID`
FROM
`users` `u`
WHERE `u`.`ID` IN
(SELECT
`u1`.`ID`
FROM
users `u1`
WHERE `u1`.`ID` IN
(SELECT
`uf`.`friendid`
FROM
user_friends `uf`
WHERE `uf`.`status` = '2'
AND `uf`.`userid` = feed_setting_user_id)
OR `u1`.`ID` IN
(SELECT
`uf2`.`userid`
FROM
`user_friends` `uf2`
WHERE `uf2`.`status` = '2'
AND `uf2`.`friendid` = feed_setting_user_id)
AND `u1`.`ID` != feed_setting_user_id);
结果:
+----+
| ID |
+----+
| 1 |
| 14 |
| 26 |
+----+
3 rows in set (0,00 sec)
递归地将上述 ID's
替换为 v_friendID
并保持 feed_setting_user_id = 15
并运行下面的 SQL
SELECT
`u`.`ID`
FROM
`users` `u`
WHERE `u`.`ID` NOT IN (feed_setting_user_id)
AND `u`.`ID` IN
(SELECT
`u1`.`ID`
FROM
`users` `u1`
WHERE `u1`.`ID` IN
(SELECT
`uf`.`friendid`
FROM
`user_friends` `uf`
WHERE `uf`.`status` = '2'
AND `uf`.`userid` = v_friendID
AND `uf`.`friendid` != v_friendID)
OR `u1`.`ID` IN
(SELECT
`uf2`.`userid`
FROM
`user_friends` `uf2`
WHERE `uf2`.`status` = '2'
AND `uf2`.`friendid` = v_friendID
AND `uf2`.`userid` != v_friendID)
AND `u1`.`ID` != v_friendID);
结果如下:
替换 v_friendID = 1
和 feed_setting_user_id = 15
+----+
| ID |
+----+
| 2 |
| 3 |
| 5 |
| 6 |
| 7 |
| 8 |
| 9 |
| 11 |
| 19 |
| 20 |
+----+
10 rows in set (0,00 sec)
替换 v_friendID = 14
和 feed_setting_user_id = 15
+----+
| ID |
+----+
| 15 |
| 25 |
+----+
2 rows in set (0,00 sec)
替换 v_friendID = 26
和 feed_setting_user_id = 15
Empty set (0,00 sec)
value=15 的 ID 被保存到 unique_tbl
中。但不适用于值为 25 的 ID
最佳答案
BEGIN
DECLARE v_friendID, FoFID BIGINT; # use datatype which is used for u.ID used int based on ur result
DECLARE exit_loop, exit_loop1 BOOLEAN DEFAULT FALSE;
DECLARE friend_cursor CURSOR FOR
SELECT `u`.`ID` FROM `users` `u`
WHERE `u`.`ID` IN (SELECT `u1`.`ID` FROM users `u1`
WHERE `u1`.`ID` IN (SELECT `uf`.`friendid` FROM user_friends `uf` WHERE `uf`.`status` = '2' AND `uf`.`userid` = feed_setting_user_id )
OR `u1`.`ID` IN (SELECT `uf2`.`userid` FROM `user_friends` `uf2` WHERE `uf2`.`status` = '2' AND `uf2`.`friendid` = feed_setting_user_id)
AND `u1`.`ID` != feed_setting_user_id);
DECLARE CONTINUE HANDLER FOR NOT FOUND SET exit_loop = TRUE;
DROP TEMPORARY TABLE IF EXISTS unique_tbl; #precaution: when sp stops with error
CREATE TEMPORARY TABLE unique_tbl (user_id BIGINT UNIQUE); #to avoid duplicate added unique
INSERT INTO unique_tbl VALUES (feed_setting_user_id); # added input from sp
OPEN friend_cursor;
friend_loop: LOOP
FETCH friend_cursor INTO v_friendID;
IF exit_loop THEN
LEAVE friend_loop;
ELSE
REPLACE INTO unique_tbl VALUES (v_friendID); # since we need all unique id's using replace if exists
fof: BEGIN
DECLARE friend_of_friend_cursor CURSOR FOR
SELECT `u`.`ID` FROM `users` `u` WHERE `u`.`ID` NOT IN (feed_setting_user_id) AND `u`.`ID`
IN (SELECT `u1`.`ID` FROM `users` `u1`
WHERE `u1`.`ID` IN (SELECT `uf`.`friendid` FROM `user_friends` `uf` WHERE `uf`.`status` = '2' AND `uf`.`userid` = v_friendID AND `uf`.`friendid` != v_friendID)
OR `u1`.`ID` IN (SELECT `uf2`.`userid` FROM `user_friends` `uf2` WHERE `uf2`.`status` = '2' AND `uf2`.`friendid` = v_friendID AND `uf2`.`userid` != v_friendID)
AND `u1`.`ID` != v_friendID );
DECLARE CONTINUE HANDLER FOR NOT FOUND SET exit_loop1 = TRUE;
OPEN friend_of_friend_cursor;
friend_of_friend_loop: LOOP
FETCH friend_of_friend_cursor INTO FoFID;
IF exit_loop1 THEN
LEAVE friend_of_friend_loop;
END IF;
REPLACE INTO unique_tbl VALUES (FoFID);
END LOOP friend_of_friend_loop;
CLOSE friend_of_friend_cursor;
SET exit_loop1 = FALSE;
END;
END IF;
END LOOP friend_loop;
CLOSE friend_cursor;
SET exit_loop = FALSE;
SELECT GROUP_CONCAT(user_id) FROM unique_tbl; #this will show result in comma seperated 2,34,56,78
#cleanup
DROP TEMPORARY TABLE IF EXISTS unique_tbl;
END$$
DELIMITER ;
关于mysql - 使用存储过程游标存储数据的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57159270/