Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/64.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在MySQL上正确循环存储函数?_Mysql_Loops_Stored Functions - Fatal编程技术网

如何在MySQL上正确循环存储函数?

如何在MySQL上正确循环存储函数?,mysql,loops,stored-functions,Mysql,Loops,Stored Functions,我在获取一个非常简单的存储过程时遇到了一些困难。 考虑下面的文章表片段: id replaced_by baseID 1 2 0 2 3 0 3 0 0 一个简单的分层表,使用写时复制。编辑文章时,当前文章的“替换对象”字段将设置为其新副本的id 我添加了一个baseID字段,将来它应该存储文章的baseID。 在我上面的例子中,有一篇文章(例

我在获取一个非常简单的存储过程时遇到了一些困难。 考虑下面的文章表片段:

id    replaced_by     baseID
 1              2          0
 2              3          0
 3              0          0
一个简单的分层表,使用写时复制。编辑文章时,当前文章的“替换对象”字段将设置为其新副本的id

我添加了一个baseID字段,将来它应该存储文章的baseID。 在我上面的例子中,有一篇文章(例如ID3)。它的baseID应该是1

为了获取baseID,我创建了以下存储过程:

DELIMITER $$

CREATE FUNCTION getBaseID(articleID INT) RETURNS INT
BEGIN
    DECLARE x INT;
    DECLARE y INT;
    SET x = articleID;
    sloop:LOOP
        SELECT id INTO y FROM article WHERE replaced_by_articleID = x;
        IF y IS NOT NULL THEN
            SET x = y;
            ITERATE sloop;
        ELSE
            LEAVE sloop;
        END IF;  
    END LOOP;
    RETURN x;
END $$

DELIMITER ;
这似乎很简单,直到我实际使用以下方法调用函数:

SELECT getBaseID(3);
我希望函数返回1。我甚至愿意理解这可能需要一秒钟的时间。 相反,机器的CPU增加到100%(mysqld)

我甚至用
REPEAT.重写了相同的函数。。直到
并与
同时。。执行
,最终结果相同

有人能解释为什么我的CPU进入循环时会100%上升吗

旁注:我只是想赢得时间。我在PHP中创建了完全相同的函数,它的性能很好,但我们猜测MySQL可以稍微快一点。我们需要筛选大约1800万条记录。我能节省的任何时间都是值得的

提前感谢您的帮助和/或指点


已解决的SQL:

DELIMITER $$

CREATE FUNCTION getBaseID(articleID INT) RETURNS INT
BEGIN
    DECLARE x INT;
    DECLARE y INT;
    SET x = articleID;
    sloop:LOOP
        SET y = NULL;
        SELECT id INTO y FROM article WHERE replaced_by_articleID = x;
        IF y IS NULL THEN
            LEAVE sloop;
        END IF;  
        SET x = y;
        ITERATE sloop;
    END LOOP;
    RETURN x;
END $$

DELIMITER ;
发件人:

如果查询未返回任何行,则会出现错误代码为1329的警告(无数据),并且变量值保持不变

因此,当没有使用给定的
x
找到任何记录时(
y
保持不变),就有一个无限循环
请尝试在SELECT语句(它应该是循环中的第一个语句)之前添加
SET y=(SELECT id…)
SET y=null

您可能会感觉到在“替换为”列上缺少索引。如果没有索引被替换,那么每次迭代都要进行一次完整的表扫描

ALTER TABLE article ADD INDEX (replaced_by);
在检索之前,还应确保该行存在

DELIMITER $$

CREATE FUNCTION getBaseID(articleID INT) RETURNS INT
BEGIN
    DECLARE x INT;
    DECLARE y INT;
    SET x = articleID;
    sloop:LOOP
        SELECT COUNT(1) INTO y FROM article WHERE replaced_by = x;
        IF y > 0 THEN
            SELECT id INTO y FROM article WHERE replaced_by = x;
            SET x = y;
        ELSE
            LEAVE sloop;
        END IF;  
    END LOOP;
    RETURN x;
END $$

DELIMITER ;
SQL调用的数量是原来的两倍,但安全性比抱歉要好


试试看

天哪,非常感谢你。我确实在INTO位上读了这一页,但我不明白它们对vars不变意味着什么。是的,索引是可用的。但搜索不存在的行是我测试的目的。它指示我何时找到baseID!