PL/SQL存储过程DBMS_OUTPUT.PUT_LINE输出异常问题排查
问题排查结论
核心原因:PL/SQL 中的本地变量是独立存储在内存中的,对数据库表执行UPDATE操作只会修改数据库里的持久化数据,不会自动同步更新到提前声明的本地变量中,必须主动做赋值/重新查询操作才能更新变量值。
具体代码问题点
- 员工薪资更新后未同步变量:更新员工薪资后,没有重新查询最新薪资到
V_SALARY变量,也没有手动修改变量值,直接输出了UPDATE之前存入的旧值,导致员工的前后两次输出完全一致。 - 经理薪资更新后未同步变量:和员工的问题一致,更新经理薪资后,
V_MANG_SAL变量里存的还是UPDATE之前查询的旧值,直接输出自然和前一次结果相同。
修复方案
有两种修复方式,可按需选择:
方案1:UPDATE后手动给变量赋值(性能更优,无需额外查询数据库)
修改后的完整代码如下:
CREATE OR REPLACE PROCEDURE SET_SALARY (P_EMP_ID NUMBER , P_ADD_SAL NUMBER) IS V_NAME VARCHAR2(50) ; V_SALARY NUMBER ; V_MANG_NAME VARCHAR2(50); V_MANG_SAL NUMBER ; V_EMP_ID NUMBER ; V_MNG_ID NUMBER ; BEGIN SELECT LAST_NAME , SALARY INTO V_NAME , V_SALARY FROM EMPLOYEES WHERE EMPLOYEE_ID = P_EMP_ID ; DBMS_OUTPUT.PUT_LINE (V_NAME || ' Before: '||V_SALARY ); UPDATE EMPLOYEES SET SALARY = SALARY + P_ADD_SAL WHERE EMPLOYEE_ID = P_EMP_ID ; -- 手动更新员工薪资变量 V_SALARY := V_SALARY + P_ADD_SAL; DBMS_OUTPUT.PUT_LINE (V_NAME || ' After: '||V_SALARY ); SELECT E.EMPLOYEE_ID , E.LAST_NAME, E.SALARY ,E.MANAGER_ID,M.LAST_NAME , M.SALARY INTO V_EMP_ID, V_NAME , V_SALARY ,V_MNG_ID,V_MANG_NAME , V_MANG_SAL FROM EMPLOYEES E , EMPLOYEES M WHERE E.MANAGER_ID = M.EMPLOYEE_ID AND E.EMPLOYEE_ID = P_EMP_ID ; DBMS_OUTPUT.PUT_LINE (V_MANG_NAME || ' Before: '||V_MANG_SAL ); UPDATE EMPLOYEES SET SALARY = SALARY + ( P_ADD_SAL / 2 ) WHERE EMPLOYEE_ID = V_MNG_ID ; -- 手动更新经理薪资变量 V_MANG_SAL := V_MANG_SAL + (P_ADD_SAL / 2); DBMS_OUTPUT.PUT_LINE (V_MANG_NAME || ' AFTER: '||V_MANG_SAL ); END ; /
方案2:UPDATE后重新查询最新数据到变量(适合逻辑复杂、无法确定更新后准确值的场景)
仅需要在每次UPDATE之后增加一次对应人员的薪资查询即可,以员工部分为例:
UPDATE EMPLOYEES SET SALARY = SALARY + P_ADD_SAL WHERE EMPLOYEE_ID = P_EMP_ID ; -- 重新查询数据库获取最新薪资 SELECT SALARY INTO V_SALARY FROM EMPLOYEES WHERE EMPLOYEE_ID = P_EMP_ID; DBMS_OUTPUT.PUT_LINE (V_NAME || ' After: '||V_SALARY );
内容的提问来源于stack exchange,提问作者Ahmed Allam
相关产品推荐
相关产品推荐

