【发布时间】:2019-12-01 05:04:45
【问题描述】:
在这里,我正在尝试实现以下存储过程。但价值没有按预期保存
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)
值=15 的 ID 正在保存到 unique_tbl。但不适用于 value=25 的 ID
【问题讨论】:
-
我没有检查这是否真的会导致您的问题(或者是否还有其他问题),但它突然出现在我身上,所以您应该尝试一下:您没有重置
exit_loop1在inner friend_of_friend_loop-loop 之前到false。所以你第二次去那里,已经是真的了,马上就停下来。 -
是的!你的权利@Solarflare
-
有没有其他更好的方法来做同样的事情? @Solarflare
-
您的意思是替代您的程序?可能,看起来a recursive query 可能能够实现相同的效果(尽管正如我所说,我实际上并没有完全检查您的代码)。虽然决定它是否“更好”(更快/更容易理解/适应/...)取决于您。
标签: mysql sql stored-procedures cursor