MySQL select 存储过程中的语句 returns 与过程外部不同的结果
MySQL select statement in stored proc returns different results than outside of proc
我无法弄清楚为什么 运行 在 mysql 过程之外的完全相同的查询在其中 return 没有相同的数据。
这是过程。
DELIMITER $$
USE `poll_app`$$
DROP PROCEDURE IF EXISTS `record_new_vote`$$
CREATE DEFINER=`somemysqluser`@`%` PROCEDURE `record_new_vote`(
p_member_id INT (10),
p_option_ids VARCHAR(255), -- 12,13,14,15
p_option_id INT (10),
p_stream_id INT (10),
p_scene_id INT (10)
)
BEGIN
DECLARE _user_already_voted VARCHAR(255);
DECLARE _update_off_id INT;
DECLARE _update_on_id INT;
-- 1. Query to figure out what to update
SELECT
p_member_id, p_option_ids, p_option_id, p_stream_id, p_scene_id;
SET SESSION group_concat_max_len = 1000000;
SELECT
GROUP_CONCAT(selections.status, "~~~", selections.id, "~~~", selections.option_id),
GROUP_CONCAT(IF(selections.status = "ON", id, NULL)),
GROUP_CONCAT(IF(selections.status = "OFF" && selections.option_id = p_option_id, selections.id, NULL))
INTO
_user_already_voted, _update_off_id, _update_on_id
FROM
selections
WHERE
selections.member_id = p_member_id
AND
selections.option_id IN (p_option_ids)
AND
selections.stream_id = p_stream_id
AND
selections.scene_id = p_scene_id;
-- 2. Check to see if the user has already voted on the poll or not
IF (_user_already_voted IS NOT NULL) THEN
SELECT
_user_already_voted, _update_off_id, _update_on_id;
END IF;
END$$
DELIMITER ;
这是它的输出
[ [ RowDataPacket {
p_member_id: 107,
p_option_ids: '1005,1006,1007,1008',
p_option_id: 1007,
p_stream_id: 7,
p_scene_id: 1 } ],
[ RowDataPacket {
_user_already_voted: 'OFF~~~451~~~1005',
_update_off_id: NULL,
_update_on_id: NULL } ],
当我 运行 select 在 proc 外部查询时(插入相同的数据)
SELECT
GROUP_CONCAT(`status`, "~~~", id, "~~~", option_id) AS "selections",
GROUP_CONCAT(IF(`status` = "ON", id, NULL)) AS "id_to_turn_status_off",
GROUP_CONCAT(IF(`status` = "OFF" && option_id = 1007, id, NULL)) AS "id_to_turn_status_on"
FROM
selections
WHERE
member_id = 107
AND
option_id IN (1005,1006,1007,1008)
AND
stream_id = 7
AND
scene_id = 1
结果
selections id_to_turn_status_off id_to_turnstatus_on
OFF~~~451~~~1005,ON~~~452~~~1006 452 null
如您所见,组连接字符串没有那么长,id_to_turn_status_off 是 452,而变量 _update_off_id 在相同查询 运行 中为 NULL过程。
我一辈子都弄不明白这个问题,如果有任何帮助,我们将不胜感激。
伙计们,我明白了。
显然
IN("1005,1006,1007,1008")
不等同于
IN(1005,1006,1007,1008)
在我在过程中的查询中,因为它接受的参数是一个字符串,所以它使用双引号版本“1005,1006,1007,1008”,而我在 运行 外面的查询是非双引号版本 1005,1006,1007,1008
这就是造成差异的原因。
我用这个改正了它
FIND_IN_SET(selections.option_id, p_option_ids)
或在查询之外
FIND_IN_SET(selections.option_id, "1005,1006,1007,1008")
很高兴你明白了:)
它似乎部分起作用的原因是类型转换。
p_option_ids VARCHAR(255)
p_option_id INT (10),
selections.option_id IN (p_option_ids)
这是试图在 VARCHAR 中找到一个 INT。 MySQL 将字符串动态转换为 int,因此它沿着字符串向下移动,直到找到一个非数字字符并截断其余字符。 “1005,1006,1007,1008”转换为 1005(截断“,1006,1007,1008”)。这就是为什么它找到 option_id=1005 行而不是 option_id=1007 行的原因。
我无法弄清楚为什么 运行 在 mysql 过程之外的完全相同的查询在其中 return 没有相同的数据。
这是过程。
DELIMITER $$
USE `poll_app`$$
DROP PROCEDURE IF EXISTS `record_new_vote`$$
CREATE DEFINER=`somemysqluser`@`%` PROCEDURE `record_new_vote`(
p_member_id INT (10),
p_option_ids VARCHAR(255), -- 12,13,14,15
p_option_id INT (10),
p_stream_id INT (10),
p_scene_id INT (10)
)
BEGIN
DECLARE _user_already_voted VARCHAR(255);
DECLARE _update_off_id INT;
DECLARE _update_on_id INT;
-- 1. Query to figure out what to update
SELECT
p_member_id, p_option_ids, p_option_id, p_stream_id, p_scene_id;
SET SESSION group_concat_max_len = 1000000;
SELECT
GROUP_CONCAT(selections.status, "~~~", selections.id, "~~~", selections.option_id),
GROUP_CONCAT(IF(selections.status = "ON", id, NULL)),
GROUP_CONCAT(IF(selections.status = "OFF" && selections.option_id = p_option_id, selections.id, NULL))
INTO
_user_already_voted, _update_off_id, _update_on_id
FROM
selections
WHERE
selections.member_id = p_member_id
AND
selections.option_id IN (p_option_ids)
AND
selections.stream_id = p_stream_id
AND
selections.scene_id = p_scene_id;
-- 2. Check to see if the user has already voted on the poll or not
IF (_user_already_voted IS NOT NULL) THEN
SELECT
_user_already_voted, _update_off_id, _update_on_id;
END IF;
END$$
DELIMITER ;
这是它的输出
[ [ RowDataPacket {
p_member_id: 107,
p_option_ids: '1005,1006,1007,1008',
p_option_id: 1007,
p_stream_id: 7,
p_scene_id: 1 } ],
[ RowDataPacket {
_user_already_voted: 'OFF~~~451~~~1005',
_update_off_id: NULL,
_update_on_id: NULL } ],
当我 运行 select 在 proc 外部查询时(插入相同的数据)
SELECT
GROUP_CONCAT(`status`, "~~~", id, "~~~", option_id) AS "selections",
GROUP_CONCAT(IF(`status` = "ON", id, NULL)) AS "id_to_turn_status_off",
GROUP_CONCAT(IF(`status` = "OFF" && option_id = 1007, id, NULL)) AS "id_to_turn_status_on"
FROM
selections
WHERE
member_id = 107
AND
option_id IN (1005,1006,1007,1008)
AND
stream_id = 7
AND
scene_id = 1
结果
selections id_to_turn_status_off id_to_turnstatus_on
OFF~~~451~~~1005,ON~~~452~~~1006 452 null
如您所见,组连接字符串没有那么长,id_to_turn_status_off 是 452,而变量 _update_off_id 在相同查询 运行 中为 NULL过程。
我一辈子都弄不明白这个问题,如果有任何帮助,我们将不胜感激。
伙计们,我明白了。
显然
IN("1005,1006,1007,1008")
不等同于
IN(1005,1006,1007,1008)
在我在过程中的查询中,因为它接受的参数是一个字符串,所以它使用双引号版本“1005,1006,1007,1008”,而我在 运行 外面的查询是非双引号版本 1005,1006,1007,1008
这就是造成差异的原因。
我用这个改正了它
FIND_IN_SET(selections.option_id, p_option_ids)
或在查询之外
FIND_IN_SET(selections.option_id, "1005,1006,1007,1008")
很高兴你明白了:)
它似乎部分起作用的原因是类型转换。
p_option_ids VARCHAR(255)
p_option_id INT (10),
selections.option_id IN (p_option_ids)
这是试图在 VARCHAR 中找到一个 INT。 MySQL 将字符串动态转换为 int,因此它沿着字符串向下移动,直到找到一个非数字字符并截断其余字符。 “1005,1006,1007,1008”转换为 1005(截断“,1006,1007,1008”)。这就是为什么它找到 option_id=1005 行而不是 option_id=1007 行的原因。