MySQL WHILE Loop Error: Use in Stored Procedures Only

Answered using ChatGPT 4o by ChatGPT4o

Question:

1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'WHILE (1) DO -- 创建临时表存储子查询结果 CREATE TEMPORARY ' at line 1

原始代码为: SET @batch_size = 1000; SET @offset = 0;

WHILE (1) DO -- 创建临时表存储子查询结果 CREATE TEMPORARY TABLE sub_table AS SELECT NEWS_ID FROM news_security_score WHERE RELATED_DEGREE = 2 LIMIT @batch_size OFFSET @offset;

-- 如果没有更多数据,退出循环
IF (SELECT COUNT(*) FROM sub_table) = 0 THEN
    LEAVE;
END IF;

-- 执行连接查询
SELECT news_tag_v1.*
FROM news_tag_v1
JOIN sub_table ON news_tag_v1.NEWS_ID = sub_table.NEWS_ID;

-- 清空临时表
DROP TEMPORARY TABLE sub_table;

-- 更新偏移量
SET @offset = @offset + @batch_size;

END WHILE;

Answer:

在 MySQL 中,WHILE 循环只能在存储过程或存储函数中使用。你不能在普通的 SQL 脚本中直接使用 WHILE 循环。你需要将你的代码放在一个存储过程里。

以下是如何将你的代码转换为存储过程的示例:

DELIMITER //

CREATE PROCEDURE process_news_tags()
BEGIN
    DECLARE batch_size INT DEFAULT 1000;
    DECLARE offset INT DEFAULT 0;
    DECLARE done INT DEFAULT 0;

    -- 声明游标
    DECLARE cur CURSOR FOR
        SELECT NEWS_ID
        FROM news_security_score
        WHERE RELATED_DEGREE = 2
        LIMIT batch_size OFFSET offset;

    -- 声明处理程序
    DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;

    -- 开始循环
    WHILE done = 0 DO
        -- 创建临时表存储子查询结果
        CREATE TEMPORARY TABLE sub_table AS
        SELECT NEWS_ID
        FROM news_security_score
        WHERE RELATED_DEGREE = 2
        LIMIT batch_size OFFSET offset;

        -- 如果没有更多数据,退出循环
        IF (SELECT COUNT(*) FROM sub_table) = 0 THEN
            LEAVE;
        END IF;

        -- 执行连接查询
        SELECT news_tag_v1.*
        FROM news_tag_v1
        JOIN sub_table ON news_tag_v1.NEWS_ID = sub_table.NEWS_ID;

        -- 清空临时表
        DROP TEMPORARY TABLE sub_table;

        -- 更新偏移量
        SET offset = offset + batch_size;
    END WHILE;
END //

DELIMITER ;

然后你可以通过以下命令调用这个存储过程:

CALL process_news_tags();

请注意,存储过程中的 WHILE 循环和游标的使用方式可能会根据你的具体需求进行调整。上面的代码只是一个基本的示例,可能需要根据你的实际情况进行修改。