2023年6月23日发(作者:)
ORACLESELECTINTO语法ORA-01422、ORA-01403错误的解决⽅案背景Oracle函数或存储过程中,对变量赋值通常会⽤到如下语法:--
单变量赋值SELECT [字段1] INTO [变量1] FROM [数据表] WHERE [查询条件];--
多变量赋值SELECT [字段1], [字段2] INTO [变量1], [变量2] FROM [数据表] WHERE [查询条件];找坑以下⽰例都以多变量赋值为例说明, 单变量赋值⾃⾏参考修改即可正常情况:--
找到指定的⼀条数据SET SERVEROUTPUT ON;DECLARE v_user_name VARCHAR2(50); v_emp_name VARCHAR2(50);BEGIN SELECT 'zhangs' AS user_name, '张三' AS emp_name
INTO v_user_name, v_emp_name
FROM DUAL
WHERE 1=1;
DBMS__LINE('v_user_name:'|| v_user_name || ', v_emp_name: ' || v_emp_name);END;--
输出结果: v_user_name:zhangs, v_emp_name:
张三情况1: 查询找到多条数据SET SERVEROUTPUT ON;DECLARE v_user_name VARCHAR2(50); v_emp_name VARCHAR2(50);BEGIN SELECT user_name, emp_name
INTO v_user_name, v_emp_name
FROM ( --
模拟源查询返回多条结果 SELECT 'zhangs' AS user_name, '张三' AS emp_name FROM DUAL UNION ALL SELECT 'lis' AS user_name, '李四' AS emp_name FROM DUAL );
DBMS__LINE('v_user_name:'|| v_user_name || ', v_emp_name: ' || v_emp_name);END;--
输出结果: ORA-01422:
实际返回的⾏数超出请求的⾏数情况2: 查询找不到数据SET SERVEROUTPUT ON;DECLARE v_user_name VARCHAR2(50); v_emp_name VARCHAR2(50);BEGIN SELECT 'zhangs' AS user_name, '张三' AS emp_name
INTO v_user_name, v_emp_name
FROM DUAL --
模拟找不到任何数据 WHERE 1=0;
DBMS__LINE('v_user_name:'|| v_user_name || ', v_emp_name: ' || v_emp_name);END;
--
输出结果: ORA-01403:
未找到任何数据如上⽰例, 我们主要需要处理查询⽆结果集返回和返回多条结果集的情况填坑情况1: 查询找到多条数据SET SERVEROUTPUT ON;DECLARE v_user_name VARCHAR2(50); v_emp_name VARCHAR2(50);BEGIN SELECT user_name, emp_name
INTO v_user_name, v_emp_name
FROM ( --
模拟源查询返回多条结果 SELECT 'zhangs' AS user_name, '张三' AS emp_name FROM DUAL UNION ALL SELECT 'lis' AS user_name, '李四' AS emp_name FROM DUAL )
--
通过只取第⼀⾏来消除报错 WHERE ROWNUM = 1;
DBMS__LINE('v_user_name:'|| v_user_name || ', v_emp_name: ' || v_emp_name);END;--
输出结果: v_user_name:zhangs, v_emp_name:
张三注意不建议采⽤这种⽅式处理如果数据有重复, 建议先去重再赋值如果结果返回了多条数据且不重复说明与预期业务逻辑不符,建议让接⼝报错再排错当前项⽬遇到这种坑,就是因为其他同事随机取了⼀条,导致最终写⼊其他业务表的字段值匹配不上,最终引起功能紊乱情况2: 查询找不到数据⽅案1: 先通过COUNT函数统计数据条数, 如果为1条则赋值SET SERVEROUTPUT ON;DECLARE v_count int; v_user_name VARCHAR2(50); v_emp_name VARCHAR2(50);BEGIN --
先查询可赋值数据总条数 SELECT COUNT(1) INTO v_count FROM ( SELECT 'zhangs' AS user_name, '张三' AS emp_name FROM DUAL WHERE 1=0 );
--
判断可赋值数据总条数再做后续处理 IF v_count = 1 THEN SELECT 'zhangs' AS user_name, '张三' AS emp_name INTO v_user_name, v_emp_name FROM DUAL WHERE 1=0; END IF; DBMS__LINE('v_user_name:'|| v_user_name || ', v_emp_name: ' || v_emp_name);END;⽅案2: 利⽤DUAL表查NULL赋值利⽤DUAL查询字段值, 如果有值则返回指定值, 如果没有值则返回NULL, 可以再加其他内置函数处理, 如NVL等SET SERVEROUTPUT ON;DECLARE v_user_name VARCHAR2(50); v_emp_name VARCHAR2(50);BEGIN --
单字段赋值(适⽤:
只查⼀个字段、查询字段少且SQL短) SELECT (SELECT 'zhangs' AS user_name FROM DUAL WHERE 1=0) INTO v_user_name FROM DUAL; SELECT (SELECT '张三' AS emp_name FROM DUAL WHERE 1=0) INTO v_emp_name FROM DUAL;
--
多字段赋值(使⽤:
查多个字段或SQL⽐较复杂) WITH TEMP AS ( --
模拟找不到结果集 SELECT 'zhangs' AS user_name, '张三' AS emp_name FROM DUAL WHERE 1=0 ) SELECT (SELECT user_name FROM temp), (SELECT emp_name FROM temp) INTO v_user_name, v_emp_name FROM DUAL; DBMS__LINE('v_user_name:'|| v_user_name || ', v_emp_name: ' || v_emp_name);END;--
输出结果: v_user_name:, v_emp_name:
总结1. 对于违背预期逻辑的情况,⼀定不要为了解决报错⽽做临时⽅案处理,避免加⼤后期问题排查难度⽐如返回多条数据,随机取第⼀条的处理⽅案2. 单字段 / 多字段赋值,如果采⽤ COUNT 判断的⽅案,则后续维护过程中,如果修改了赋值的SQL语句,⼀定要记得修改COUNT判断SQL3. 单字段 / 多字段赋值, 如果采⽤ 利⽤DUAL 的⽅案,注意适⽤场景1. 如果是单字段或较少字段, SQL简单的情况,则可以采⽤单字段SQL赋值2. 如果是较多字段或多字段, SQL复杂的情况, 则可以采⽤ WITH TEMP AS + DUAL赋值
发布者:admin,转转请注明出处:http://www.yc00.com/web/1687517102a16315.html
评论列表(0条)