如何理解导致 MySQL 函数中截断不正确的双值错误的原因?

Posted

技术标签:

【中文标题】如何理解导致 MySQL 函数中截断不正确的双值错误的原因?【英文标题】:How to understand what causes Truncated incorrect double value error in MySQL Function? 【发布时间】:2018-10-09 11:45:32 【问题描述】:

我有一个表格,其中包含以下形式的子父关系:

+----+-----------+
| id | nParent   |
+----+-----------+
|  1 |         0 |
|  2 |         1 |
|  3 |         2 |
|  4 |         3 |
|  5 |         3 |
|  6 |         4 |
+----+-----------+

此表表示我要抽象的对象之间的树(多级,n 元)关系。应用程序的其余部分已经使用了这个层次结构,并且很容易获得一个孩子的父母或父母的孩子。但是,我现在正在尝试解决一个问题,即我需要一个节点下的子树中的所有元素。在寻找答案时,我发现了一个 amazing solution on DBA Stack Exchange,它为这个要求创建了一个函数。这是我在必要修改后的代码:

CREATE FUNCTION `GetFamilyTree`(GivenID INT) RETURNS varchar(1024) CHARSET latin1
DETERMINISTIC
BEGIN

DECLARE rv,q,queue,queue_children VARCHAR(1024);
DECLARE queue_length,front_id,pos INT;

SET rv = '';
SET queue = GivenID;
SET queue_length = 1;

WHILE queue_length > 0 DO
    SET front_id = FORMAT(queue,0);
    IF queue_length = 1 THEN
        SET queue = '';
    ELSE
        SET pos = LOCATE(',',queue) +1 ;
        SET q = SUBSTR(queue,pos);
        SET queue = q;
    END IF;
    SET queue_length = queue_length - 1;

    SELECT IFNULL(qc,'') INTO queue_children
    FROM (SELECT GROUP_CONCAT(id) qc
    FROM nodes WHERE nParent = front_id) A;

    IF LENGTH(queue_children) = 0 THEN
        IF LENGTH(queue) = 0 THEN
            SET queue_length = 0;
        END IF;
    ELSE
        IF LENGTH(rv) = 0 THEN
            SET rv = queue_children;
        ELSE
            SET rv = CONCAT(rv,',',queue_children);
        END IF;
        IF LENGTH(queue) = 0 THEN
            SET queue = queue_children;
        ELSE
            SET queue = CONCAT(queue,',',queue_children);
        END IF;
        SET queue_length = LENGTH(queue) - LENGTH(REPLACE(queue,',','')) + 1;
    END IF;
END WHILE;

RETURN rv;

END

但是,当我运行它时,我收到一条错误消息 错误代码:1292。截断不正确的 DOUBLE 值 '14,15,16'*

我逐部分重写了函数,并且各个部分(查询等)运行良好。但是在函数中,它会抛出错误。

可能出了什么问题? 我怎样才能找到导致错误的确切原因?

【问题讨论】:

您可能试图将字符串与数字进行比较并自动转换是在抱怨。 我唯一能看到你可能会尝试使用逗号分隔的字符串作为数字的地方是 SET front_id = FORMAT(queue,0); 如果你首先将 queue 转换为 unsigned 会发生什么,即SET front_id = FORMAT(CAST(queue AS UNSIGNED),0);? @Nick 错误没有变化。 是否有机会发布足够的数据来在 SQLFiddle 上复制问题? @Aditya 我对问题行的看法是对的,对解决方案是错误的。看我的回答。 【参考方案1】:

你的问题出在这一行:

SET front_id = FORMAT(queue,0);

queue 是逗号分隔的值列表,mysql 不希望将其转换为数值。将此行更改为

SET front_id = cast(substring_index(queue, ',', 1) as unsigned);

解决问题。请参阅此demo on rextester,您可以在其中尝试在两行代码之间进行更改。

【讨论】:

不用担心。很高兴我能帮上忙。

以上是关于如何理解导致 MySQL 函数中截断不正确的双值错误的原因?的主要内容,如果未能解决你的问题,请参考以下文章

将文件中的双值数字读入 C++ 中的向量并访问它们的值

将双值截断到小数点后6位。

我无法使用 bigquery 将数字转换为 float64,不断出现错误的双值错误

将 UDF 从 MS SQL Server 移植到 MySQL 会引发异常不正确的双精度值

数据截断:不正确的日期时间值:''

MySQL 截断不正确的 DOUBLE 值?