SpringBoot项目调用数据库函数报错Result consisted of more than one row

这个报错太具有误导性了,致使我们花了好长时间,采用了很多错误的解决方案。

项目中有一个表,有idqr_codeparent_qr_code这3个字段,层级没有限制。有时候需要在代码中查询某个qr_code的顶级qr_code,用代码写递归查询感觉效率会比较差,所以写了个函数来查root节点:

sql 复制代码
BEGIN
    DECLARE current_qrcode VARCHAR(255);
    DECLARE parent_qrcode VARCHAR(255);

    SET current_qrcode = start_qrcode;

    -- 防止无限循环,设置最大层级
    SET @max_level = 100;
    SET @current_level = 0;

    loop_label: LOOP
        SET @current_level = @current_level + 1;

        -- 如果超过最大层级,退出循环
        IF @current_level > @max_level THEN
            LEAVE loop_label;
        END IF;

        -- 查询当前记录的父级
        SELECT t.parent_qr_code INTO parent_qrcode
        FROM qr_tree t
        WHERE t.qr_code = current_qrcode;

        -- 如果没有父级或者父级为空,说明找到顶级
        IF parent_qrcode IS NULL OR parent_qrcode = '' THEN
            LEAVE loop_label;
        ELSE
            SET current_qrcode = parent_qrcode;
        END IF;
    END LOOP;

    RETURN current_qrcode;
END

在测试环境之前走的一切正常,但是今天上生产环境突然报错:

shell 复制代码
### Cause: java.sql.SQLSyntaxErrorException: Result consisted of more than one row
; bad SQL grammar []; nested exception is java.sql.SQLSyntaxErrorException: Result consisted of more than one row
org.springframework.jdbc.BadSqlGrammarException: 
### Error querying database.  Cause: java.sql.SQLSyntaxErrorException: Result consisted of more than one row
### The error may exist in URL [jar:file:/home/PROJECT/spring-boot-system.jar!/BOOT-INF/lib/spring-boot-business.jar!/org/qrTree/mapper/xml/QrTree.xml]
### The error may involve defaultParameterMap
### The error occurred while setting parameters
### SQL: select * from qr_tree where qr_code = (SELECT find_top_qrcode(?)) limit 1
### Cause: java.sql.SQLSyntaxErrorException: Result consisted of more than one row
; bad SQL grammar []; nested exception is java.sql.SQLSyntaxErrorException: Result consisted of more than one row

这个报错太具有误导性了,一开始一看到这个报错,就觉得是函数或者整条SQL返回了多条数据,而只能接收一条所报的错,于是在Navicat里各种执行,发现都没问题,但是在项目里就是会报错。

代码改来改去都不行,不如给函数后面加个LIMIT 1,或者去掉嵌套式的查询直接qr_code=find_top_qrcode(),结果发现依然报错。

然后就给函数里面的查询加了个LIMIT 1,就是这一段:

sql 复制代码
SELECT t.parent_qr_code INTO parent_qrcode
FROM qr_tree t
WHERE t.qr_code = current_qrcode LIMIT 1;

然后发现果然不报错了。

就在我们以为万事大吉之后,发现了另一个问题:这个业务操作之后,这个表中的qr_code列会出现重复。

经过代码的梳理,我发现我本来写的是replace info,因为数据库的ID没有自增,所以手动设置了UUID,这时候就发现问题了,生产环境的数据库没!有!设!置!唯!一!键!

如果设置了唯一键,这个表的qr_code就不可能重复。那么加上唯一键,刚才的报错会消失吗?

我加上了唯一键,并且去掉了刚才胡乱添加的LIMIT 1,再跑一遍代码,果然,不报错了!

相关推荐
葫芦和十三3 小时前
图解 MongoDB 05|文档模型设计:内嵌 vs 引用,反范式不是免费午餐
后端·mongodb·agent
不能放弃治疗7 小时前
单 Agent 实现模式
后端
IT_陈寒9 小时前
Redis内存爆了,原来我漏掉了这个致命配置
前端·人工智能·后端
fliter10 小时前
最后一块拼图:用 bitvec 构造 IPv4 包,真正做出自己的 Ping
后端
用户35218024547511 小时前
🎆从 Prompt 到 Skill:让 Spring AI Agent 学会"装新技能"
人工智能·spring boot·ai编程
fliter11 小时前
用 Rust 解析并生成 ICMP 包:checksum、nom 与 cookie-factory
后端
蝎子莱莱爱打怪11 小时前
XZLL-IM干货系列 03|消息 ID 设计:一个 UUID 搞不定的事,我用两个 ID 解决了
后端·面试·开源
fliter11 小时前
从 panic 到 Result:用 Rust 重新整理一个 ping 项目的错误处理
后端
森蓝情丶11 小时前
我给 AI 搭了个法庭:一个前端仔的 LangGraph 实战全记录
前端·后端
JensCS猿12 小时前
从 Spring Boot 回看 SSM 框架:手动挡与自动挡的驾驶哲学
后端