Oracle游标的执行相关问题
来源:互联网 发布:linux 查看mysql版本 编辑:程序博客网 时间:2024/05/29 14:25
背景:今天在处理生产上的数据写了一个存储过程,处理一个主从表的数据。最终执行结果预期与实际结果不符。最终根本原因在于游标的使用:游标在打开的时候,才会真正的执行游标定义的select语句,若在打开前游标前,存储过程中其他部分对数据进行修改,则打开游标获取的数据,是修改后的数据。
废话不多说,上代码。
- create or replace procedure EF_EARNEABILL_procedure
- as
- --游标一 实收单单头
- cursor cur1 is
- SELECT
- T.EAR_ID as EAR_ID,
- T.EAR_NO ||T.ORG_ID as EAR_NO
- FROM
- (
- SELECT
- EF.EAR_ID,
- EF.EAR_NO,
- EF.ORG_ID
- FROM
- EF_EARNEABILL EF
- LEFT JOIN ES_USER ES ON ES.ESUS_ID = EF.CREATOR
- WHERE EF.EAR_NO IN(SELECT EAR_NO FROM EF_EARNEABILL WHERE 1=1 GROUP BY EAR_NO HAVING COUNT(1)>1)
- )T
- ;
- --游标二 实收单明细
- cursor cur2 is
- SELECT
- T.EARENT_ID as EARENT_ID,
- T.EARENT_EAR_NO || T.ORG_ID as EARENT_EAR_NO
- FROM
- (
- SELECT
- EF.EARENT_ID,
- EF.EARENT_EAR_NO,
- EF.ORG_ID
- FROM
- EF_EARNEABILLENTRY EF
- LEFT JOIN ES_USER ES ON ES.ESUS_ID = EF.CREATOR
- WHERE EF.EARENT_EAR_NO IN(SELECT EAR_NO FROM EF_EARNEABILL WHERE 1=1 GROUP BY EAR_NO HAVING COUNT(1)>1)
- )T
- ;
- begin
- --遍历实收单头游标结果,后根据结果更新数据
- for cur_result1 in cur1 loop
- update EF_EARNEABILL set EAR_NO = cur_result1.EAR_NO where EAR_ID = cur_result1.EAR_ID;
- end loop;
- --遍历实收明细游标结果,后根据结果更新数据
- for cur_result2 in cur2 loop
- update EF_EARNEABILLENTRY set EARENT_EAR_NO = cur_result2.EARENT_EAR_NO where EARENT_ID = cur_result2.EARENT_ID;
- end loop;
- end EF_EARNEABILL_procedure;
大家注意看红色游标打开部分:首先打开了游标cur1,遍历游标,并根据游标获取的值更新了实收单头数据,然后打开游标cur2,遍历游标,
获取游标值,更新实收明细明细,ok, 没毛病,执行存储过程去。
运行结果:单头数据更新正确,明细数据未变化。
分析: 明细没有变化,说明明细对应的游标cur2,没有查到相关值呗!但,我在运行存过过程之前,是有单独运行游标sql语句的,是有相关数据的,
说明什么?说明在运行存储过程当中值是有变化的,大家可以查看蓝色部分代码,此语句是获取相关的单号,游标cur1、cur2都是使用,
这相关的单号.但是单头数据更新正确,说明蓝色部分代码查询的单号是存在的,可是明明使用的相同代码却没获取到相关单号(因为明细数据未变化),
这是为什么呢?哦,原来我们在遍历游标cur1,后此时实收单头,实收单号已经被更新,对蓝色获取相关单号语句查询结果是有影响的。此时问题已经很明朗了,
原来游标执行是打开的时候,才开始真正的去执行select,所以当我们打开cur2时候,select获取到的结果是更新后的结果,没有获取到正确的结果,
最终出现单头数据更新正确,明细数据未变化 现象。
原因:游标的实际运行时期为开启游标动作开始时.
问题原因找到了,修改就好办了,我们只需要将实收单明细游标操作及更新数据放在 更新单头之前,即可。
更改后代码:
- create or replace procedure EF_EARNEABILL_procedure
- as
- --游标一 实收单单头
- cursor cur1 is
- SELECT
- T.EAR_ID as EAR_ID,
- T.EAR_NO ||T.ORG_ID as EAR_NO
- FROM
- (
- SELECT
- EF.EAR_ID,
- EF.EAR_NO,
- EF.ORG_ID
- FROM
- EF_EARNEABILL EF
- LEFT JOIN ES_USER ES ON ES.ESUS_ID = EF.CREATOR
- WHERE EF.EAR_NO IN(SELECT EAR_NO FROM EF_EARNEABILL WHERE 1=1 GROUP BY EAR_NO HAVING COUNT(1)>1)
- )T
- ;
- --游标二 实收单明细
- cursor cur2 is
- SELECT
- T.EARENT_ID as EARENT_ID,
- T.EARENT_EAR_NO || T.ORG_ID as EARENT_EAR_NO
- FROM
- (
- SELECT
- EF.EARENT_ID,
- EF.EARENT_EAR_NO,
- EF.ORG_ID
- FROM
- EF_EARNEABILLENTRY EF
- LEFT JOIN ES_USER ES ON ES.ESUS_ID = EF.CREATOR
- WHERE EF.EARENT_EAR_NO IN(SELECT EAR_NO FROM EF_EARNEABILL WHERE 1=1 GROUP BY EAR_NO HAVING COUNT(1)>1)
- )T
- ;
- begin
- --遍历实收明细游标结果,后根据结果更新数据
- for cur_result2 in cur2 loop
- update EF_EARNEABILLENTRY set EARENT_EAR_NO = cur_result2.EARENT_EAR_NO where EARENT_ID = cur_result2.EARENT_ID;
- end loop;
- --遍历实收单头游标结果,后根据结果更新数据
- for cur_result1 in cur1 loop
- update EF_EARNEABILL set EAR_NO = cur_result1.EAR_NO where EAR_ID = cur_result1.EAR_ID;
- end loop;
- end EF_EARNEABILL_procedure;
经检验,运行结果正确。
阅读全文
0 0
- Oracle游标的执行相关问题
- Oracle游标的问题
- Oracle的游标isLast()问题
- oracle的游标控制问题
- (Oracle)游标的相关知识和实例
- Oracle游标执行流程
- oracle游标相关
- oracle: 游标,父游标,子游标,游标相关视图
- C#执行oracle返回游标类型的存储过程
- 游标的相关知识
- Oracle执行计划的相关概念
- Oracle执行计划的相关概念
- Oracle执行计划的相关概念
- oracle 清除相关对象的执行计划
- Oracle执行计划的相关概念
- ORACLE获得执行计划的相关视图
- [转]Oracle执行计划的相关概念
- oracle执行存储过程返回游标cursor
- AppStore发布流程
- C
- 使用inline-block进行二栏以及三栏布局以及各种布局方式链接
- java 用数组实现队列
- 2js变量
- Oracle游标的执行相关问题
- if (!IsPostBack)作用
- 实模式和保护模式虚拟地址映射
- 如何修改公网ip和mac地址
- 桥接(Bridge)模式
- 使用selenium抓取最右搞笑视频存入本地python3
- ARM汇编中ldr与adr的区别
- WebSocket中,onopen携带参数
- fragment重叠问题解决方案