【发布时间】:2018-01-04 00:32:06
【问题描述】:
如果我按原样运行这个存储过程,它会给出不正确的返回值,并且当我检查我的日志时,它永远不会记录 else 条件:
CREATE DEFINER=`root`@`localhost` PROCEDURE `rpt_PlayerOnlineTime`(IN ucid VARCHAR(128), INOUT totaltime INT)
BEGIN
DECLARE v_finished INTEGER DEFAULT 0;
DECLARE v_event varchar(20) DEFAULT "";
DECLARE v_time BIGINT DEFAULT 0;
DECLARE v_server_id INT DEFAULT 0;
DECLARE v_session_id INT DEFAULT 0;
DECLARE v_start BIGINT DEFAULT 0;
DECLARE v_end BIGINT;
DEClARE con_cursor CURSOR FOR
SELECT type, real_time, server_id, session_id FROM ki.raw_connection_log WHERE player_ucid = ucid;
-- declare NOT FOUND handler
DECLARE CONTINUE HANDLER
FOR NOT FOUND SET v_finished = 1;
CALL ki.log("rpt_PlayerOnlineTime", CONCAT("totaltime: ", totaltime));
OPEN con_cursor;
online_time: LOOP
CALL ki.log("rpt_PlayerOnlineTime", "In Loop");
FETCH con_cursor INTO v_event, v_time, v_server_id, v_session_id;
IF v_finished = 1 THEN
CALL ki.log("rpt_PlayerOnlineTime", "Finished Loop");
LEAVE online_time;
END IF;
IF v_event = "CONNECTED" THEN
IF v_start != 0 then
CALL ki.log("rpt_PlayerOnlineTime", "CONNECTED EVENT TWICE IN A ROW");
CALL ki.log("rpt_PlayerOnlineTime", CONCAT("v_server_id - ", v_server_id));
CALL ki.log("rpt_PlayerOnlineTime", CONCAT("v_session_id - ", v_session_id));
-- If the next event is not a disconnect event, assume that the player or server crashed, and get the time from the session
SELECT session.real_time_end INTO v_end FROM ki.session WHERE server_id = v_server_id AND session_id = v_session_id;
IF v_end IS NOT NULL THEN
CALL ki.log("rpt_PlayerOnlineTime", "SETTING v_end TO SESSION END TIME");
ELSE
SELECT session.last_heartbeat INTO v_end FROM ki.session WHERE session.server_id = v_server_id AND session.session_id = v_session_id;
CALL ki.log("rpt_PlayerOnlineTime", "SETTING v_end To Last HeartBeat Received from session");
CALL ki.log("rpt_PlayerOnlineTime", CONCAT("totaltime : ", totaltime));
CALL ki.log("rpt_PlayerOnlineTime", CONCAT("v_start : ", v_start));
IF v_end IS NULL THEN
CALL ki.log("rpt_PlayerOnlineTime", "Last Heartbeat is NULL - defaulting to start");
SET v_end = v_start; -- if the last_heartbeat is null, then assume there was no end date
END IF;
CALL ki.log("rpt_PlayerOnlineTime", CONCAT("v_end : ", v_end));
END IF;
SET totaltime = totaltime + (v_end - v_start);
END IF;
SET v_start = v_time;
ELSEIF v_event = "DISCONNECTED" THEN
CALL ki.log("rpt_PlayerOnlineTime", "DISCONNECTED EVENT - CALCULATING END TIME");
SET totaltime = totaltime + (v_time - v_start);
SET v_start = 0;
END IF;
CALL ki.log("rpt_PlayerOnlineTime", CONCAT("IN LOOP: Total Time: ", totaltime));
END LOOP online_time;
CLOSE con_cursor;
CALL ki.log("rpt_PlayerOnlineTime", CONCAT("Total Time: ", totaltime));
END
问题出在这部分代码中 - v_end 可能为 NULL,但使用当前的 if 语句它永远不会为真(我从未看到记录的 else 信息)
-- If the next event is not a disconnect event, assume that the player or server crashed, and get the time from the session
SELECT session.real_time_end INTO v_end FROM ki.session WHERE server_id = v_server_id AND session_id = v_session_id;
IF v_end IS NOT NULL THEN
CALL ki.log("rpt_PlayerOnlineTime", "SETTING v_end TO SESSION END TIME");
ELSE
SELECT session.last_heartbeat INTO v_end FROM ki.session WHERE session.server_id = v_server_id AND session.session_id = v_session_id;
CALL ki.log("rpt_PlayerOnlineTime", "SETTING v_end To Last HeartBeat Received from session");
CALL ki.log("rpt_PlayerOnlineTime", CONCAT("totaltime : ", totaltime));
CALL ki.log("rpt_PlayerOnlineTime", CONCAT("v_start : ", v_start));
IF v_end IS NULL THEN
CALL ki.log("rpt_PlayerOnlineTime", "Last Heartbeat is NULL - defaulting to start");
SET v_end = v_start; -- if the last_heartbeat is null, then assume there was no end date
END IF;
CALL ki.log("rpt_PlayerOnlineTime", CONCAT("v_end : ", v_end));
END IF;
但是,如果我将 if 语句修改为使用 != NULL,它会起作用。
-- If the next event is not a disconnect event, assume that the player or server crashed, and get the time from the session
SELECT session.real_time_end INTO v_end FROM ki.session WHERE server_id = v_server_id AND session_id = v_session_id;
IF v_end != NULL THEN
CALL ki.log("rpt_PlayerOnlineTime", "SETTING v_end TO SESSION END TIME");
ELSE
SELECT session.last_heartbeat INTO v_end FROM ki.session WHERE session.server_id = v_server_id AND session.session_id = v_session_id;
CALL ki.log("rpt_PlayerOnlineTime", "SETTING v_end To Last HeartBeat Received from session");
CALL ki.log("rpt_PlayerOnlineTime", CONCAT("totaltime : ", totaltime));
CALL ki.log("rpt_PlayerOnlineTime", CONCAT("v_start : ", v_start));
IF v_end IS NULL THEN
CALL ki.log("rpt_PlayerOnlineTime", "Last Heartbeat is NULL - defaulting to start");
SET v_end = v_start; -- if the last_heartbeat is null, then assume there was no end date
END IF;
CALL ki.log("rpt_PlayerOnlineTime", CONCAT("v_end : ", v_end));
END IF;
为什么 MySQL 会这样工作?我正在查看有关检查变量是否为空的正确方法的其他 stackoverflow 帖子,他们建议使用 IS NOT NULL 而不是 != NULL。
How to check if a variable is NULL, then set it with a MySQL stored procedure?
我正在使用 MySql 5.7.20 - 这是 MySql 中的错误吗?
【问题讨论】:
-
这是一个整数值
session.real_time_end? -
不,两者都是 bigint,它们来自第三方游戏。