`
Ivan0513
  • 浏览: 212583 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

一个入门级存储过程

 
阅读更多
create or replace procedure proc_autoAuditCreditAmount
as
  --声明游标 结果集A:需要核销的机构(有未核销单据)
  cursor ivan_cur is
    select customerDepaID, min(CreditAccount_ID) acBeginID, max(CreditAccount_ID) acEndID
    from Tbl_Creditaccount
    where alterationType<=0 and isPayback=0
    group by customerDepaID
    order by customerDepaID;
  --声明游标(带参数) 结果集B:某机构需要核销的单据,某机构的id来源于结果集A的循环
  cursor ivan_cur_b(
         p_depa_id Tbl_Creditaccount.Creditaccount_Id%type
         ,p_beginID Tbl_Creditaccount.Creditaccount_Id%type
         ,p_endID Tbl_Creditaccount.Creditaccount_Id%type ) 
    is
    select *
    from Tbl_Creditaccount
    where alterationType<=0 and isPayback=0 and customerDepaID=p_depa_id
    and CreditAccount_ID between p_beginID and p_endID
    order by alterationTime asc, CreditAccount_ID asc;

    
  --声明变量paybackmoney,它的类型是表Tbl_Creditaccount中字段Alterationamount的类型,初始化为0
  v_paybackNum number := 0; --某机构还款单数量
  v_paybackmoney Tbl_Creditaccount.Alterationamount%type := 0;--某机构还款单总金额
  v_minPaybackID Tbl_Creditaccount.Creditaccount_Id%type; --某机构还款单开始ID
  v_maxPaybackID Tbl_Creditaccount.Creditaccount_Id%type; --某机构还款单结束ID
  v_checkNum number := 0; --某机构已核销记录数量 
  v_lastSettleBalance Tbl_Cancelrecord.Settlebalance%type := 0; --某机构最后一次结余金额
  v_settleBalance Tbl_Cancelrecord.Settlebalance%type := 0;--某机构本次可用来还款的总金额
  v_totalAmount Tbl_Cancelrecord.totalamount%type := 0;--某机构本次的核销了的单据的总金额
  v_recordNo number := 0; --核销单编号yyyyMMddsys00001
  v_index number;
  v_depaName Tbl_Depa.Depaname%type := 0; --机构名称(确保最新)
  v_cancelrecord_id Tbl_Cancelrecord.cancelrecord_id%type := 0; --核销主表ID
  v_calculateenddatetime Tbl_Cancelrecord.calculateenddatetime%type; --核销结束时间
  --v_alterationAmount Tbl_Creditaccount.Alterationamount%type := 0;--某机构每笔借贷的金额
begin
  --1.循环核销每一个需要核销的机构
  for ivan_rec in ivan_cur loop
    begin
         savepoint sp1;
         v_recordNo := v_recordNo + 1;
         v_index := 0; --每次循环开头都要初始化,因为这是子循环的index
         select depaname into v_depaName from tbl_Depa where depa_id = ivan_rec.customerDepaID;--取机构此刻的名称
         --DBMS_OUTPUT.put_line('The customerID is '||ivan_rec.customerDepaID||', record from '||ivan_rec.acBeginID||' to '||ivan_rec.acEndID);
         
         --2.查找该机构可使用(未核销)的还款单总金额
         --(2.1)首先判断该机构是否有可还款的记录,防止Not_Data_Found Exception
         select count(ca.creditaccount_id) into v_paybackNum
         from Tbl_Creditaccount ca
         where alterationType=1 and isPayback=0 and customerDepaID=ivan_rec.customerDepaID;
         
         if v_paybackNum = 0 then
           v_paybackmoney := 0;
           v_minPaybackID := 0;
           v_maxPaybackID := 0;
         else 
           --(2.2)查找该机构可使用(未核销)的还款单总金额,放入变量paybackmoney
           select 
           sum(alterationamount) into v_paybackmoney
           from Tbl_Creditaccount ca
           where alterationType=1 and isPayback=0 and customerDepaID=ivan_rec.customerDepaID
           group by customerDepaID;
           
           select min(Creditaccount_Id) into v_minPaybackID
           from Tbl_Creditaccount ca
           where alterationType=1 and isPayback=0 and customerDepaID=ivan_rec.customerDepaID;
           
           select max(Creditaccount_Id) into v_maxPaybackID
           from Tbl_Creditaccount ca
           where alterationType=1 and isPayback=0 and customerDepaID=ivan_rec.customerDepaID;
         end if;
         --DBMS_OUTPUT.put_line('This agent has '||v_paybackmoney||' RMB to pay!');
         
         --3.在核销主表中,查找该机构最后一条核销记录,取出该记录的结余金额
         --(3.1)首先判断该机构是否有结余金额数据,防止Not_Data_Found Exception
         select count(cr.cancelrecord_id) into v_checkNum
         from Tbl_Cancelrecord cr
         where recordState=2 and agentDepaID=ivan_rec.customerDepaID;
         
         if v_checkNum = 0 then
           v_lastSettleBalance := 0;
         else
           --(3.2)查找机构上一次的结余金额
           select settleBalance into v_lastSettleBalance
           from (
             select rank() over(partition by agentDepaID order by cancelRecordDatetime desc, cancelRecord_ID desc) rn
             , cr.settleBalance
             from Tbl_Cancelrecord cr
             where recordState=2 and agentDepaID=ivan_rec.customerDepaID
           ) a
           where rn=1;
         end if;
         --DBMS_OUTPUT.put_line('The lastest settle Balance is '||v_lastSettleBalance||' RMB!');
         v_settleBalance := v_paybackmoney + v_lastSettleBalance;                 
         DBMS_OUTPUT.put_line('Begin : Agent '||ivan_rec.customerDepaID||'_'||v_depaName||' has '||v_settleBalance||' RMB to pay this time!' );
         
       
         
       --前面是准备工作,现在开始为机构核销单据了!
       
       --循环结果集B,核销该机构的订单
       for ivan_rec_b in ivan_cur_b(ivan_rec.customerDepaID, ivan_rec.acBeginID, ivan_rec.acEndID) loop
         begin 
           DBMS_OUTPUT.put_line('No.'||ivan_rec_b.billNo||', borrow money :'||ivan_rec_b.alterationAmount||', current settleBalance :'||v_settleBalance);
           if v_settleBalance < (-ivan_rec_b.alterationAmount) then --无法核销本单据(钱不够),跳出子循环(如果是第一笔,那么v_cancelrecord_id=0)
              DBMS_OUTPUT.put_line('无法继续核销该机构,跳出子循环!' );
              exit; 
           else 
             if v_index = 0 then --有钱核销第一笔单据,那么首先往核销主表插入一条数据
               insert into tbl_cancelrecord(
                 cancelrecord_id,agentdepaid, agentdepaname
                 ,cancelrecorddatetime,cancelrecordtype--核销种类:0人工  1自动
                 ,calculatebegindatetime--,calculateenddatetime 
                 ,cancelrecordno
                 ,createpersonid,createpersonaccount,createdepaid,createdepaname,createdatetime
                 ,lastmodifydepaid,lastmodifypersonname,lastmodifypersonid,lastmodifydepaname,lastmodifydatetime
                 ,recordstate
               )
               values(
                 seq_cancelrecord.nextval, ivan_rec_b.customerdepaid, v_depaName
                 ,sysdate, 0 --核销种类:0自动 1人工 
                 ,ivan_rec_b.alterationtime
                 ,to_char(sysdate,'yyyyMMdd')||'sys'||Lpad(v_recordNo,5,0)--核销单编号yyyyMMddsys00001
                 ,1,'Admin',3,'综合业务部',sysdate --写死
                 ,1,'Admin',3,'综合业务部',sysdate --写死
                 ,2 --已核销
               );   
               select seq_cancelrecord.currval into v_cancelrecord_id from dual; --赋值到变量,记录核销主表ID
             end if;
           end if;
           --够钱核销该单据
           --将本条单据置为已核销
           update tbl_creditaccount
           set ispayback = 1, payBackType = 0
           where creditaccount_id = ivan_rec_b.creditaccount_id;
           --插入一条核销记录至核销明细表
           insert into tbl_cancelrecorddetails(
             cancelrecorddetails_id
             ,cancelrecordid
             ,agentdepaid, agentdepaname
             ,orderid, orderno
             ,ordertype
           )
           values(
             seq_cancelrecorddetails.nextval
             ,v_cancelrecord_id
             ,ivan_rec_b.customerdepaid, v_depaName
             ,ivan_rec_b.billid, ivan_rec_b.billno
             ,ivan_rec_b.billtype
           );
           v_index := v_index + 1;
           v_settleBalance := v_settleBalance + ivan_rec_b.alterationAmount; --记住是+,因为ivan_rec_b.alterationAmount带正负号
           v_totalAmount := v_totalAmount - ivan_rec_b.alterationAmount; --记住是-,因为ivan_rec_b.alterationAmount带正负号
           v_calculateenddatetime := ivan_rec_b.alterationtime;
         end;
       end loop;
       
       if v_index > 0 then --说明本机构核销了单据      
         update tbl_cancelrecord --更新核销主表某些字段
         set calculateenddatetime = v_calculateenddatetime --本次核销最后一笔单据时间
             ,totalamount = v_totalAmount--本次共核销金额
             ,settleBalance = v_settleBalance --本次核销后,结余金额
         where cancelrecord_id = v_cancelrecord_id;
         
         update Tbl_Creditaccount --将所有未核销的还款单置为已核销(已用来还款)
         set ispayback = 1, payBackType = 0
         where alterationType=1 and isPayback=0 --单据:还款单,状态:未核销(未使用)
               and customerDepaID=ivan_rec.customerDepaID 
               --一定要加修改范围,因为这途中可能增加了未核销的还款单,虽然几率很微小
               and creditaccount_id between v_minPaybackID and v_maxPaybackID;
       end if;
       
       /*
       --测试异常
       if v_recordNo = 3 then 
         v_index := v_index / 0;
       end if;
       */
       --提交一个机构的数据
       commit;
       DBMS_OUTPUT.put_line('v_recordNo ' || v_recordNo || '-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*' );
    
    exception
    when others then
        dbms_output.put_line('Error!!!! Error on agent: ' || v_depaName); 
        rollback to savepoint sp1; --回滚数据,并继续循环下一个机构
    
    end;
  end loop;
end;

 

分享到:
评论

相关推荐

    oracle存储过程学习经典入门

    Oracle 存储过程学习经典入门 Oracle 存储过程学习目录是 Oracle 存储过程学习的基础知识,了解 Oracle 存储过程的基本语法、基础知识和一些常见问题的解决方法是非常重要的。本文将从 Oracle 存储过程的基础知识...

    SQL存储过程入门级教程

    "SQL存储过程入门级教程" SQL存储过程是数据库系统中的一种重要组件,它可以帮助开发者和DBA更好地管理和维护数据库。下面将详细介绍SQL存储过程的概念、优点、创建方法和应用场景等方面的知识点。 SQL存储过程...

    MySQL 存储过程入门到精通

    MySQL存储过程是数据库管理系统中的一个重要特性,它允许程序员或数据库管理员预先定义一组SQL语句,形成一个可重用的逻辑单元。在这个“MySQL存储过程入门到精通”资料中,你将深入理解存储过程的原理、创建、调用...

    入门级--存储过程分页.net

    在SQL Server中,创建一个存储过程来处理分页,通常包括两个输入参数:当前页码(@CurrentPage)和每页大小(@PageSize)。存储过程内部应包含SQL的OFFSET-FETCH语法(SQL2008及更高版本)或ROW_NUMBER()函数(SQL...

    MySQL存储过程入门学习

    ### MySQL存储过程入门学习 #### 一、存储过程概述 **存储过程**(Stored Procedure)是一种在数据库中存储的预先编写并编译好的SQL程序或函数集合。存储过程的主要优势在于可以提高应用程序的性能和响应速度,同时...

    HP入门级SAN存储方案

    该方案的核心是建立一个基于光纤通道的专用存储区域网络(SAN),将存储设备与服务器通过独立的网络连接,从而减轻局域网(LAN)的带宽压力,提高数据传输效率。 在传统的存储解决方案中,大量数据访问占用LAN带宽...

    msql存储过程经典教程

    此示例创建了一个名为`p`的简单存储过程,该过程实际上什么也不做。 #### 三、为何使用存储过程 存储过程提供了一系列好处: 1. **代码复用性**:存储过程可以被多次调用,减少重复代码。 2. **性能优化**:存储...

    小题大做之MySQL 5.0存储过程编程入门(转)

    MySQL 5.0 存储过程编程入门是数据库管理领域中的一个重要话题,它涉及到数据库的高级功能,使得数据库系统能够执行复杂的逻辑操作,提高数据处理的效率和安全性。存储过程是一组预先编译的SQL语句,可以在需要时被...

    这是给初学者写存储过程的实例

    本文将通过一个具体的示例来详细介绍如何为初学者编写简单的存储过程。 #### 二、存储过程概念回顾 存储过程是预编译的一组SQL语句集合,它可以存储在数据库中,并作为一个单独的对象来调用执行。与普通的SQL查询...

    存储入门基础知识

    - **独立的数据存储网络**:SAN作为一个独立的数据存储网络,与传统的LAN(局域网)分开运行,可以有效避免数据流量对业务网络的影响。 - **灵活的数据共享**:通过SAN,多个服务器可以共享同一块存储资源,提高了...

    公司系统研发讲解sqlserver的存储过程

    其中,**存储过程**是一种非常强大的工具,它可以被用来封装一组SQL语句并作为一个单独的对象存储在数据库服务器上。本文将深入探讨SQL Server存储过程的基础概念、创建方法及应用场景,旨在帮助读者快速入门并掌握...

    SQL Server 2005编程入门经典-触发器和存储过程教程

    《SQL Server 2005编程入门经典-触发器和存储过程教程》是针对初学者的一本详尽指南,旨在帮助读者深入理解SQL Server 2005中的核心概念,特别是触发器和存储过程这两大数据处理的重要工具。下面将详细阐述这两个...

    成就存储专家之路:存储从入门到精通

    - **数据加密**:利用加密算法对数据进行加密处理,确保数据在传输和存储过程中的安全性。 **3.2 云计算环境下的存储解决方案** - **公有云存储**:由第三方提供商提供的基于互联网的存储服务,具有高度的可扩展性...

    oracle存储过程学习经典入门.rar_oracle

    Oracle存储过程是数据库管理系统Oracle中的一个重要特性,它允许开发者编写一系列的SQL和PL/SQL语句,形成一个可重用的程序单元。这个压缩包文件"oracle存储过程学习经典入门.rar_oracle"显然包含了帮助初学者理解并...

    SQL Server 2005编程入门经典(第2版)之存储过程-触发器

    例如,一个存储过程可能执行一系列操作,而这些操作触发了一个或多个触发器,进一步处理数据或执行验证。 四、学习资源 "SQL Server 2005编程入门经典(第2版)之存储过程-触发器"这本书会详细讲解如何在SQL Server ...

    oralce入门级帮助文档,里面提供了分页,存储过程,数据库选择,表空间,oracle数据库基础语法,注意事项实例

    这份"oralce入门级帮助文档"将引导初学者逐步掌握Oracle数据库的基础知识,包括分页、存储过程、数据库选择、表空间以及Oracle数据库的基础语法等关键概念。 一、分页查询 在处理大量数据时,分页查询是必不可少的...

    Java入门级教程

    Java入门级教程是一个针对初学者精心设计的在线学习资源,旨在帮助那些对编程感兴趣的人们快速掌握Java语言的基础知识。这个教程以Web格式呈现,使得学习过程更加方便、直观,适合在各种设备上进行学习。 Java是一...

    python自学入门级代码

    "python自学入门级代码"这个标题暗示了我们即将探讨的内容是针对那些想要学习Python编程的新手,提供了简单易懂的代码示例,并且包含详细的注释,以帮助理解每一步的操作。 在Python的学习过程中,掌握基本语法是至...

Global site tag (gtag.js) - Google Analytics