【问题标题】:MySQL Error 1442: Can't Update Table, but Table isn't being referenced?MySQL 错误 1442:无法更新表,但未引用表?
【发布时间】:2026-02-19 18:35:01
【问题描述】:

我正在编写一个循环遍历各种昆虫收集器的程序,其中一些用逗号分隔,例如。 “V. Shirey, L. Smith”,我需要从中为每个收集器创建一个新行。我的程序如下所示:

DROP PROCEDURE IF EXISTS agent_reclamation;
DELIMITER //
CREATE PROCEDURE agent_reclamation (IN VerbatimName VARCHAR(170)) 
BEGIN
DECLARE verbatimNameHandler varchar(170);
DECLARE tempAgentName varchar(170); 
SET verbatimNameHandler = VerbatimName;
    WHILE LENGTH(verbatimNameHandler) > 0 DO -- while there's more stuff left
        IF LOCATE(',', verbatimNameHandler) > 0 THEN -- and theres a comma to be found
            SET tempAgentName = SUBSTRING(verbatimNameHandler,1,LOCATE(',',verbatimNameHandler) - 1); -- set the temp variable to everything from the first character to the first comma
        ELSE
            SET tempAgentName = verbatimNameHandler; -- set the name if there are no commas
            SET verbatimNameHandler = ''; -- won't accept procedure without update --
        END IF;
            INSERT INTO agentReclamation SET tempAgentName = tempAgentName;
        /* INSERT INTO agentReclamation(tempAgentName) VALUES (tempAgentName); */ -- insert the new names into the agentReclamation table
        SET verbatimNameHandler = REPLACE(verbatimNameHandler, tempAgentName + ',', ''); -- won't accept procedure without update --
    END WHILE;
END //

DELIMITER ;

SELECT agent_reclamation(VerbatimName) FROM tempAgent WHERE VerbatimName LIKE 
'%,%';

我收到错误 1442 说明,无法更新存储函数/触发器中的表“tempAgent”,因为它在调用此存储函数/触发器的语句中使用。我看不到我将自己定位在哪里,以便在程序的任何地方更新“tempAgent”。

任何帮助将不胜感激,我目前只是掌握编写自己的程序的窍门。谢谢!

【问题讨论】:

  • agentReclamation 上没有触发器,它对表tempAgent 有作用吗?
  • @j.kaspar 看起来他对tempAgent 表的唯一引用无论如何都在存储的过程定义之外。 Vaughn,你能在存储过程之外运行类似的插入吗?
  • @Uueerdo,我在程序之外很好地运行了插入 - 我实际上刚刚解决了这个问题。我最终需要 2 个过程:一个我定义一个游标并在调用 agent_reclamation 过程和 agent_reclamation 过程本身时遍历每一行。这里的主要违规者之一是试图在 select 语句中调用一个过程。

标签: mysql sql stored-procedures


【解决方案1】:

我所做的是创建两个过程,其中一个通过对原始过程的过程调用对每一行进行迭代。见下文:

DROP PROCEDURE IF EXISTS agent_reclamation;
DROP PROCEDURE IF EXISTS procIteration;
DELIMITER //

CREATE PROCEDURE procIteration ()
BEGIN
DECLARE done BOOLEAN DEFAULT FALSE;
DECLARE verbatimNameHandler varchar(170);
DECLARE cur CURSOR FOR SELECT VerbatimName FROM tempAgent WHERE VerbatimName LIKE '%,%';
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done := TRUE;

OPEN cur;

testLoop: LOOP
    FETCH cur INTO verbatimNameHandler;
    IF done THEN 
        LEAVE testLoop;
    END IF;
    CALL agent_reclamation(verbatimNameHandler);
END LOOP testLoop;

CLOSE cur;
END //

CREATE PROCEDURE agent_reclamation (IN VerbatimName VARCHAR(170)) 
BEGIN
DECLARE verbatimNameHandler varchar(170);
DECLARE tempAgentName varchar(170); 
SET verbatimNameHandler = VerbatimName;
    WHILE LENGTH(verbatimNameHandler) > 0 DO -- while there's more stuff left
        IF LOCATE(',', verbatimNameHandler) > 0 THEN -- and theres a comma to be found
            SET tempAgentName = SUBSTRING(verbatimNameHandler,1,LOCATE(',',verbatimNameHandler) - 1); -- set the temp variable to everything from the first character to the first comma
        ELSE
            SET tempAgentName = verbatimNameHandler; -- set the name if there are no commas
            SET verbatimNameHandler = ''; -- won't accept procedure without update --
        END IF;
        -- INSERT INTO agentReclamation SET tempAgentName = tempAgentName;
        INSERT INTO agentReclamation(tempAgentName) VALUES (tempAgentName);  -- insert the new names into the agentReclamation table
        SET verbatimNameHandler = REPLACE(verbatimNameHandler, CONCAT(tempAgentName, ','), ''); -- won't accept procedure without update --
    END WHILE;
END //

DELIMITER ;

CALL procIteration();

这会产生预期的结果。

【讨论】:

    最近更新 更多