PL/SQL存储过程PLS-00103报错排查求助(Toad环境)
PLS-00103错误原因及修复方案
核心错误原因
- 变量声明块赋值语法违规:PL/SQL的声明段(IS与BEGIN之间)不支持直接用
变量 := (SELECT ...)的方式给变量赋值标量子查询,必须使用SELECT ... INTO 变量的语法,或把赋值逻辑移到BEGIN块中执行,这是触发"遇到符号SELECT和)"错误的直接原因。 - 无接收目标的SELECT语句:BEGIN块中的SELECT语句必须将结果存入变量,PL/SQL不允许执行不返回结果到变量的裸SELECT语句。
- END后符号错误:属于前序语法错误引发的连锁问题,修复前面的语法问题后该错误会自动消失。
修复后的完整代码
CREATE OR REPLACE PROCEDURE P_SYS_APPL_TEMP_SAVE2 ( P_C_CD IN GEN3200.C_CD%TYPE , P_APPL_ID IN GEN3200.APPL_ID%TYPE , P_ITEM_CD IN GEN3200.ITEM_CD%TYPE , P_SEQ_NO IN GEN3200.SEQ_NO%TYPE , P_ITEM_SIZE_CD IN GEN3200.ITEM_SIZE_CD%TYPE , P_APPL_CNT IN GEN3200.APPL_CNT%TYPE , P_ORDER_YMD IN GEN3200.ORDER_YMD%TYPE , P_OFFER_YMD IN GEN3200.OFFER_YMD%TYPE , P_MOD_USER_ID IN GEN3200.MOD_USER_ID%TYPE , P_MOD_YMDHMS IN GEN3200.MOD_YMDHMS%TYPE ) IS APPL_TYPE VARCHAR2(20); EMP_ID VARCHAR2(20); CK_YN VARCHAR2(1); -- 新增变量接收校验结果 BEGIN -- 修复变量赋值:使用SELECT INTO语法 SELECT T1.APPL_TYPE INTO APPL_TYPE FROM SY7010 T1 , GEN3200 T2 WHERE T1.C_CD = T2.C_CD AND T2.C_CD = P_C_CD AND T1.APPL_ID = T2.APPL_ID AND T2.APPL_ID = P_APPL_ID; SELECT T1.APPL_EMP_ID INTO EMP_ID FROM SY7010 T1 , GEN3200 T2 WHERE T1.C_CD = T2.C_CD AND T2.C_CD = P_C_CD AND T1.APPL_ID = T2.APPL_ID AND T2.APPL_ID = P_APPL_ID; -- 修复SELECT语句:添加INTO接收查询结果 SELECT CASE WHEN PERIOD_CD IS NULL THEN 'Y' WHEN (CK_CNT + P_APPL_CNT) <= LIMIT_CNT THEN 'Y' ELSE 'N' END INTO CK_YN FROM ( SELECT SUM(CASE WHEN T3.PERIOD_CD = '1' AND TO_CHAR(TO_DATE(T1.APPL_YMD, 'YYYYMMDD'), 'YYYY') = TO_CHAR(SYSDATE, 'YYYY') THEN T2.APPL_CNT WHEN T3.PERIOD_CD = '2' AND TO_CHAR(TO_DATE(T1.APPL_YMD, 'YYYYMMDD'), 'MM') = TO_CHAR(SYSDATE, 'MM') THEN T2.APPL_CNT WHEN T3.PERIOD_CD = '3' AND T1.APPL_YMD = TO_CHAR(SYSDATE, 'YYYYMMDD') THEN T2.APPL_CNT ELSE 0 END) AS CK_CNT , T3.PERIOD_CD , T3.LIMIT_CNT FROM SY7010 T1 , GEN3200 T2 , GEN3100 T3 WHERE T1.C_CD = P_C_CD AND T1.APPL_TYPE = APPL_TYPE AND T1.TRG_EMP_ID = EMP_ID AND TO_CHAR(TO_DATE(T1.APPL_YMD, 'YYYYMMDD'), 'YYYY') = TO_CHAR(SYSDATE, 'YYYY') AND T2.C_CD = T1.C_CD AND T2.APPL_ID = T1.APPL_ID AND T2.ITEM_CD = P_ITEM_CD AND T2.SEQ_NO = P_SEQ_NO AND T3.C_CD = T2.C_CD AND T3.ITEM_CD = T2.ITEM_CD AND T3.SEQ_NO = T2.SEQ_NO GROUP BY T3.PERIOD_CD, T3.LIMIT_CNT ); -- 可选:根据校验结果添加逻辑,比如校验不通过时终止执行 IF CK_YN = 'N' THEN RAISE_APPLICATION_ERROR(-20001, '申请数量超出限制'); END IF; INSERT INTO GEN3200 ( C_CD , APPL_ID , ITEM_CD , SEQ_NO , ITEM_SIZE_CD , APPL_CNT , ORDER_YMD , OFFER_YMD , MOD_USER_ID , MOD_YMDHMS ) VALUES ( P_C_CD , P_APPL_ID , P_ITEM_CD , P_SEQ_NO , P_ITEM_SIZE_CD , P_APPL_CNT , P_ORDER_YMD , P_OFFER_YMD , P_MOD_USER_ID , P_MOD_YMDHMS ); COMMIT; END P_SYS_APPL_TEMP_SAVE2; /
额外排查建议
- 确保子查询唯一性:如果
SY7010与GEN3200的关联查询可能返回多条记录,需添加ROWNUM = 1或调整数据逻辑保证唯一结果,避免触发TOO_MANY_ROWS异常。 - 处理空结果场景:添加异常处理块捕获
NO_DATA_FOUND,避免子查询无结果时存储过程崩溃。 - 优化表连接语法:将逗号分隔的隐式连接改为显式
JOIN语法,提升代码可读性和维护性。
内容的提问来源于stack exchange,提问作者seunghyub
相关产品推荐
相关产品推荐

