MYSQL 游标运行 没完没了
MYSQL Cursor running endlessly
好吧,首先免责声明:我知道使用游标是数据库编程最糟糕的做法之一,但我没有找到任何其他方法来做到这一点。
我正在创建一个类似于 blog/chat 的应用程序,以便我们的员工可以与客户沟通,并保存所有 company/client 交互并添加时间戳(有一些响应时间投诉)。
无论如何,我一直在努力跟踪未读消息,所以我想如果我知道每个用户已经阅读了哪些消息,我可以做一个简单的数学计算,所以每当我的应用程序调用消息时 table 对于消息,它将更新一个名为 "Read messages" 的单独 table,我将在其中跟踪已阅读的消息。
我想我有逻辑,但每当我尝试 运行 它时,mysql 只是挂起思考直到它超时,但是,如果我检查 'messages read' table,信息确实更新了。
代码如下:
BEGIN
DROP TEMPORARY TABLE IF EXISTS fetchedMessages;
CREATE TEMPORARY TABLE fetchedMessages AS (
SELECT
blg.pkIdEntrada AS idMensaje,
blg.grlContenido AS Contenido,
blg.grlTimestamp AS FechaHora,
blg.grlReferencia AS Referencia,
usu.pkIdUsuario AS IdUsuario,
usu.gPrimerNombre AS PrimerNombre,
usu.gPrimerApellido AS PrimerApellido,
tml.pkIdRead AS idLectura
FROM blgEntries blg
LEFT JOIN tbl_usuarios usu ON blg.fkIdUsuario = usu.pkIdUsuario
LEFT JOIN tbl_mensajesLeidos tml ON blg.pkIdEntrada = tml.fkIdMensaje AND blg.fkIdUsuario = tml.fkIdUser
WHERE
blg.grlReferencia = numReferencia
ORDER BY
FechaHora DESC
);
BEGIN
DECLARE done INT DEFAULT FALSE;
DECLARE c_idMess INT;
DECLARE curs CURSOR
FOR SELECT idMensaje FROM fetchedMessages WHERE idLectura IS NULL AND idMensaje IS NOT NULL;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
OPEN curs;
LOOP
FETCH curs INTO c_idMess;
INSERT INTO tbl_mensajesLeidos (fkIdMensaje, fkIdUser) VALUES (c_idMess, idEmp) ON DUPLICATE KEY UPDATE fkIdMensaje = c_IdMess, fkIdUser = idEmp;
##SELECT CONCAT(c_idMess, ' - ', idEmp);
END LOOP;
CLOSE curs;
END;
SELECT * FROM fetchedMessages;
END
有什么想法吗??
您没有退出循环。
的示例
另一个重要的:尝试使用一个简单的INSERT ... SELECT语句来代替游标。该语句允许从另一个数据集中插入数据。它还将完全简化您的代码。
我看到的大多数与 MySql 游标和循环相关的示例明确检查循环中找到的变量的真实条件,在您的情况下为 1,如果为真则退出循环。你似乎错过了那一步。
我也很好奇为什么如果您将 found 变量声明为整数,您会将其默认为 false 而不是 0。
好吧,首先免责声明:我知道使用游标是数据库编程最糟糕的做法之一,但我没有找到任何其他方法来做到这一点。
我正在创建一个类似于 blog/chat 的应用程序,以便我们的员工可以与客户沟通,并保存所有 company/client 交互并添加时间戳(有一些响应时间投诉)。
无论如何,我一直在努力跟踪未读消息,所以我想如果我知道每个用户已经阅读了哪些消息,我可以做一个简单的数学计算,所以每当我的应用程序调用消息时 table 对于消息,它将更新一个名为 "Read messages" 的单独 table,我将在其中跟踪已阅读的消息。
我想我有逻辑,但每当我尝试 运行 它时,mysql 只是挂起思考直到它超时,但是,如果我检查 'messages read' table,信息确实更新了。
代码如下:
BEGIN
DROP TEMPORARY TABLE IF EXISTS fetchedMessages;
CREATE TEMPORARY TABLE fetchedMessages AS (
SELECT
blg.pkIdEntrada AS idMensaje,
blg.grlContenido AS Contenido,
blg.grlTimestamp AS FechaHora,
blg.grlReferencia AS Referencia,
usu.pkIdUsuario AS IdUsuario,
usu.gPrimerNombre AS PrimerNombre,
usu.gPrimerApellido AS PrimerApellido,
tml.pkIdRead AS idLectura
FROM blgEntries blg
LEFT JOIN tbl_usuarios usu ON blg.fkIdUsuario = usu.pkIdUsuario
LEFT JOIN tbl_mensajesLeidos tml ON blg.pkIdEntrada = tml.fkIdMensaje AND blg.fkIdUsuario = tml.fkIdUser
WHERE
blg.grlReferencia = numReferencia
ORDER BY
FechaHora DESC
);
BEGIN
DECLARE done INT DEFAULT FALSE;
DECLARE c_idMess INT;
DECLARE curs CURSOR
FOR SELECT idMensaje FROM fetchedMessages WHERE idLectura IS NULL AND idMensaje IS NOT NULL;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
OPEN curs;
LOOP
FETCH curs INTO c_idMess;
INSERT INTO tbl_mensajesLeidos (fkIdMensaje, fkIdUser) VALUES (c_idMess, idEmp) ON DUPLICATE KEY UPDATE fkIdMensaje = c_IdMess, fkIdUser = idEmp;
##SELECT CONCAT(c_idMess, ' - ', idEmp);
END LOOP;
CLOSE curs;
END;
SELECT * FROM fetchedMessages;
END
有什么想法吗??
您没有退出循环。
的示例另一个重要的:尝试使用一个简单的INSERT ... SELECT语句来代替游标。该语句允许从另一个数据集中插入数据。它还将完全简化您的代码。
我看到的大多数与 MySql 游标和循环相关的示例明确检查循环中找到的变量的真实条件,在您的情况下为 1,如果为真则退出循环。你似乎错过了那一步。
我也很好奇为什么如果您将 found 变量声明为整数,您会将其默认为 false 而不是 0。