• PLSQL 创建带返回数据集的Function


    分享之前,真诚感谢IT 张工(巨林)的支持!!

    聊起工序流程设置、条码追溯,就有点头大!!实话,接到BOSS下达的这个Task, 心里没个底,开始时心慌慌^_^ 。原因之前在Oracle仅仅是增、删、改查,至多加个transaction。

    因为数据使用报表工具显示,因此不能使用C# 等后台代码进行控制与计算,初步判定: Procedure 或者 Function.

    首先Procedure和Function 都支持输入参数与输出结果,但各有优劣: procedure 方便过程控制、Insert , Update 等操作,但返回结果集通常使用Cursor;Function 虽然能返回DataTable 数据集,但不支持DML 语句,Insert , Update 就会报错(其实有条件支持);

    在经历了N次尝试,失败,尝试,失败。。。。后,最终决定采用Function 来实现。

    技术方面的总结如下:

    1. 由于Function 不能在函数体中声明Cursor(只能在is … Begin 之间), 因此无法实现随着情况变化而变的Cursor(此前没有搞清楚,Fetch cursor 老是报错,郁闷了好久);
    2. 在IT 张工建议下,使用For in loop 替代Cursor ,非常好的建议;
    3. 在创建Function 前,先Create TYPE {typename} table of …; 然后才能在 定义Function 中return TypeName(变量列表之后);
    4. Function 内部默认是只读的,也就是只能使用Select 或者 Select into ; 要使用Insert , Update , Delete 等DML语句,必须使用PRAGMA AUTONOMOUS_TRANSACTION 声明,且 commit 语句不能少哦;
    5. 一旦执行commit 语句,临时表就会清空;因此需要在commit 执行前转存临时表的结果;
    6. Select .. into …  当查询结果为空时,会报错: 没有查询记录;
    7. 前面工作准备好了,返回结果相当简单: Select * from table(fn_CalcLineProcTime_Nov('A4305','2021-11-2',4));

    上代码:

    /*************************
             工序时间计算
    *****************************/
    create or replace function fn_CalcLineProcTime_Nov(
           p_LineNo varchar2,
           p_BegDate varchar2,
           p_Hours number
           --,p_ProcName varchar2
           )
           return PROC_Time_Table
     as
     PRAGMA AUTONOMOUS_TRANSACTION;
            v_procData PROC_Time_Table:=PROC_Time_Table();
            v_CELLName varchar2(100):='';      --条码
            v_ParentSN varchar2(100):=null;        --父条码
            --v_SubSN varchar2(100):='';           --子条码
            v_bJump boolean:=false;                --是否跳过
            v_ProcName varchar2(32):='';         --工序名
            v_rowcount number:=0;            --记录行数
            v_ParentSNCount number:=0;
            
     begin
       --将指定时期内 BarCode 最早出现的时间插入至临时表
       Insert into tb_LineProcTime_new(SN,Proc_Name,Test_Time,NextProcTime,PassTime,Line_No,PN,Flow_Type)
       Select SN,Proc_Name,Test_Time,NextProcTime,PassTime,Line_No,PN,Flow_Type
       from(
         select ROW_Number() over(partition by a.SN order by a.Test_Time) rn,a.* 
         FROM (Select SN,Proc_Name,Test_Time,null NextProcTime,null PassTime,Line_No,PN,Remark_1 Flow_Type 
           from NVT_PROCESS_STATUS 
           where Test_Type=1 and Test_CNT=1 and RT_CNT=0 and Line_No is not null 
           and Line_No=p_LineNo 
           --and Line_No='A4305'
           and Test_Time>To_Date(p_BegDate,'YYYY-MM-DD') and Test_Time<To_Date(p_BegDate,'YYYY-MM-DD')+p_Hours/24) a)
           --and Test_Time>To_Date('2021-10-27','YYYY-MM-DD') and Test_Time<To_Date('2021-10-27','YYYY-MM-DD')+4/24) a)
        where rn=1
        order by Test_Time,SN;
        
        --select * from tb_LineProcTime 
        for tb in(Select SN,Proc_Name,Test_Time,PN,Flow_Type from tb_LineProcTime_new  order by Test_Time,SN,Proc_Name) loop
            v_CellName:=tb.SN;
            v_ProcName:=tb.Proc_Name;
            for flow in(Select cp.Proc_Name,cp.Proc_Idx,p.proc_flag,p.Data_Tb_Name,Proc_Tb_Name from Nvt_Cp_List_01 cp inner join NVT_Proc_Matchtb p on cp.Proc_Name=p.Proc_Name 
                        where cp.PN=tb.PN and cp.Flow_Type=tb.Flow_Type and cp.Test_Type=1 and cp.Status_Flag='生效'
                        and cp.Proc_Idx>(Select Proc_Idx from NVT_CP_List_01 where PN=tb.PN and Flow_Type=tb.Flow_Type and Test_Type=1 and Proc_Name=tb.Proc_Name)
                        order by cp.Proc_Idx) loop
                if flow.data_tb_name='NA' and flow.proc_tb_name='NA' then
                   v_bJump:=true;
                   --if v_ProcName='' then v_ProcName:=tb.Proc_Name; end if;
                   continue;
                end if;
                if flow.Proc_Name='CLINK' then 
                  Select Count(SN) into v_ParentSNCount from NVT_CELL_GROUP where CELL_Name=v_CellName and LINK_DATE>To_Date(p_BegDate,'YYYY-MM-DD') and LINK_DATE<=To_Date(p_BegDate,'YYYY-MM-DD')+p_Hours/24;
                  exit when v_ParentSNCount=0;
                  
                  Select SN into v_ParentSN from NVT_CELL_GROUP where CELL_Name=v_CellName and LINK_DATE>To_Date(p_BegDate,'YYYY-MM-DD') and LINK_DATE<=To_Date(p_BegDate,'YYYY-MM-DD')+p_Hours/24;
                  --exit when v_ParentSN is null; 
                  select Count(1) into v_rowcount from tb_LineProcTime_new where SN=v_ParentSN and Proc_Name=flow.Proc_Name ;
                  if v_rowcount=0 then  --插入过站数据
                      Insert into tb_LineProcTime_new(SN,Proc_Name,Test_Time,NextProcTime,PassTime,Line_No,PN,Flow_Type)
                             Select SN,Proc_Name,Test_Time,null NextProcName,null PassTime,Line_No,PN,Remark_1 Flow_Type
                             from NVT_PROCESS_STATUS 
                             where Test_Type=1 and Test_CNT=1 and RT_CNT=0 
                             and Line_No=p_LineNo
                             and SN=v_ParentSN
                             and Proc_Name=flow.Proc_Name
                             and Test_Time>To_Date(p_BegDate,'YYYY-MM-DD') and Test_Time<To_Date(p_BegDate,'YYYY-MM-DD')+p_Hours/24;
                   end if;
                  --更新上一站的结束时间
                  Update tb_LineProcTime_new t1 
                  SET t1.NextProctime=(Select t2.Test_Time from tb_LineProcTime_new t2 where t2.Proc_Name=flow.Proc_Name AND t2.SN=v_ParentSN)
                  where SN=v_CellName and Proc_name=v_ProcName; 
                  
                elsif flow.Proc_Name='PCM-ASM' then
                       Select Count(CELL_NAME) into v_ParentSNCount from NVT_PCM_ASM where SUB_CELL_NAME=v_CellName and Update_Date>to_Date(p_BegDate,'YYYY-MM-DD') and Update_Date<To_Date(p_BegDate,'YYYY-MM-DD')+p_Hours/24;
                       exit when v_ParentSNCount=0;
                       Select CELL_NAME into v_ParentSN from NVT_PCM_ASM where SUB_CELL_NAME=v_CellName and Update_Date>to_Date(p_BegDate,'YYYY-MM-DD') and Update_Date<To_Date(p_BegDate,'YYYY-MM-DD')+p_Hours/24;
                       --exit when v_ParentSN is null; 
                       select Count(1) into v_rowcount from tb_LineProcTime_new where SN=v_ParentSN and Proc_Name=flow.Proc_Name ;
                       if v_rowcount=0 then
                         Insert into tb_LineProcTime_new(SN,Proc_Name,Test_Time,NextProcTime,PassTime,Line_No,PN,Flow_Type)
                         Select SN,Proc_Name,Test_Time,null NextProcName,null PassTime,Line_No,PN,Remark_1 Flow_Type
                             from NVT_PROCESS_STATUS 
                             where Test_Type=1 and Test_CNT=1 and RT_CNT=0 
                             and Line_No=p_LineNo
                             and SN=v_ParentSN
                             and Proc_Name=flow.Proc_Name
                             and Test_Time>To_Date(p_BegDate,'YYYY-MM-DD') and Test_Time<To_Date(p_BegDate,'YYYY-MM-DD')+p_Hours/24;
                       end if;
                       --更新上一站的结束时间
                        Update tb_LineProcTime_new t1
                        SET t1.NextProctime=(Select t2.Test_Time from tb_LineProcTime_new t2 where t2.Proc_Name=flow.Proc_Name AND t2.SN=v_ParentSN)
                        where SN=v_CellName and Proc_name=v_ProcName;
                 elsif flow.Proc_Name='MOD-ASM' then  --NVT_MODULE_ASM
                       Select Count(CELL_NAME) into v_ParentSNCount from NVT_MODULE_ASM where SUB_CELL_NAME=v_CellName and Update_Date>to_Date(p_BegDate,'YYYY-MM-DD') and Update_Date<To_Date(p_BegDate,'YYYY-MM-DD')+p_Hours/24;
                       exit when v_ParentSNCount=0;
                       Select CELL_NAME into v_ParentSN from NVT_MODULE_ASM where SUB_CELL_NAME=v_CellName and Update_Date>to_Date(p_BegDate,'YYYY-MM-DD') and Update_Date<To_Date(p_BegDate,'YYYY-MM-DD')+p_Hours/24;
                       --exit when v_ParentSN is null;
                       select Count(1) into v_rowcount from tb_LineProcTime_new where SN=v_ParentSN and Proc_Name=flow.Proc_Name ;
                       if v_rowcount=0 then
                         Insert into tb_LineProcTime_new(SN,Proc_Name,Test_Time,NextProcTime,PassTime,Line_No,PN,Flow_Type)
                         Select SN,Proc_Name,Test_Time,null NextProcName,null PassTime,Line_No,PN,Remark_1 Flow_Type
                             from NVT_PROCESS_STATUS 
                             where Test_Type=1 and Test_CNT=1 and RT_CNT=0 
                             and Line_No=p_LineNo
                             and SN=v_ParentSN
                             and Proc_Name=flow.Proc_Name
                             and Test_Time>To_Date(p_BegDate,'YYYY-MM-DD') and Test_Time<To_Date(p_BegDate,'YYYY-MM-DD')+p_Hours/24;
                        end if;   
                        --更新上一站的结束时间
                        Update tb_LineProcTime_new t1
                        SET t1.NextProctime=(Select t2.Test_Time from tb_LineProcTime_new t2 where t2.Proc_Name=flow.Proc_Name AND t2.SN=v_ParentSN)
                        where SN=v_CellName and Proc_name=v_ProcName;                      
                elsif flow.Proc_Name='WELDING' then  --NVT_WELDING
                       Select Count(CELL_NAME) into v_ParentSNCount from NVT_WELDING where SUB_CELL_NAME=v_CellName and Update_Date>to_Date(p_BegDate,'YYYY-MM-DD') and Update_Date<To_Date(p_BegDate,'YYYY-MM-DD')+p_Hours/24;
                       exit when v_ParentSNCount=0;
                       Select CELL_NAME into v_ParentSN from NVT_WELDING where SUB_CELL_NAME=v_CellName and Update_Date>to_Date(p_BegDate,'YYYY-MM-DD') and Update_Date<To_Date(p_BegDate,'YYYY-MM-DD')+p_Hours/24;
                       --exit when v_ParentSN is null;
                       select Count(1) into v_rowcount from tb_LineProcTime_new where SN=v_ParentSN and Proc_Name=flow.Proc_Name ;
                       if v_rowcount=0 then
                         Insert into tb_LineProcTime_new(SN,Proc_Name,Test_Time,NextProcTime,PassTime,Line_No,PN,Flow_Type)
                         Select SN,Proc_Name,Test_Time,null NextProcName,null PassTime,Line_No,PN,Remark_1 Flow_Type
                             from NVT_PROCESS_STATUS 
                             where Test_Type=1 and Test_CNT=1 and RT_CNT=0 
                             and Line_No=p_LineNo
                             and SN=v_ParentSN
                             and Proc_Name=flow.Proc_Name
                             and Test_Time>To_Date(p_BegDate,'YYYY-MM-DD') and Test_Time<To_Date(p_BegDate,'YYYY-MM-DD')+p_Hours/24;
                        end if;  
                        --更新上一站的结束时间
                        Update tb_LineProcTime_new t1
                        SET t1.NextProctime=(Select t2.Test_Time from tb_LineProcTime_new t2 where t2.Proc_Name=flow.Proc_Name AND t2.SN=v_ParentSN)
                        where SN=v_CellName and Proc_name=v_ProcName;                       
                elsif flow.Proc_Name='MAPPING' then  --NVT_LABEL_MAPPING
                       Select Count(CELL_NAME) into v_ParentSNCount from NVT_LABEL_MAPPING where SUB_CELL_NAME=v_CellName and Update_Date>to_Date(p_BegDate,'YYYY-MM-DD') and Update_Date<To_Date(p_BegDate,'YYYY-MM-DD')+p_Hours/24;
                       exit when v_ParentSNCount=0;
                       Select CELL_NAME into v_ParentSN from NVT_LABEL_MAPPING where SUB_CELL_NAME=v_CellName and Update_Date>to_Date(p_BegDate,'YYYY-MM-DD') and Update_Date<To_Date(p_BegDate,'YYYY-MM-DD')+p_Hours/24;
                       --exit when v_ParentSN is null;
                       select Count(1) into v_rowcount from tb_LineProcTime_new where SN=v_ParentSN and Proc_Name=flow.Proc_Name ;
                       if v_rowcount=0 then
                         Insert into tb_LineProcTime_new(SN,Proc_Name,Test_Time,NextProcTime,PassTime,Line_No,PN,Flow_Type)
                         Select SN,Proc_Name,Test_Time,null NextProcName,null PassTime,Line_No,PN,Remark_1 Flow_Type
                             from NVT_PROCESS_STATUS 
                             where Test_Type=1 and Test_CNT=1 and RT_CNT=0 
                             and Line_No=p_LineNo
                             and SN=v_ParentSN
                             and Proc_Name=flow.Proc_Name
                             and Test_Time>To_Date(p_BegDate,'YYYY-MM-DD') and Test_Time<To_Date(p_BegDate,'YYYY-MM-DD')+p_Hours/24;
                        end if;
                        --更新上一站的结束时间
                        Update tb_LineProcTime_new t1
                        SET t1.NextProctime=(Select t2.Test_Time from tb_LineProcTime_new t2 where t2.Proc_Name=flow.Proc_Name AND t2.SN=v_ParentSN)
                        where SN=v_CellName and Proc_name=v_ProcName;
                elsif flow.Proc_Name='CARTON' then  --NVT_LOT_MAPPING
                       --Select CELL_NAME into v_ParentSN from NVT_LABEL_MAPPING where SUB_CELL_NAME=v_CellName and Update_Date>to_Date(p_BegDate,'YYYY-MM-DD') and Update_Date<To_Date(p_BegDate,'YYYY-MM-DD')+p_Hours/24;
                       select Count(1) into v_rowcount from tb_LineProcTime_new where SN=v_CellName and Proc_Name=flow.Proc_Name ;
                       if v_rowcount=0 then
                         Insert into tb_LineProcTime_new(SN,Proc_Name,Test_Time,NextProcTime,PassTime,Line_No,PN,Flow_Type)
                         Select SN,Proc_Name,Test_Time,null NextProcName,null PassTime,Line_No,PN,Remark_1 Flow_Type
                             from NVT_PROCESS_STATUS 
                             where Test_Type=1 and Test_CNT=1 and RT_CNT=0 
                             and Line_No=p_LineNo
                             and SN=v_CellName
                             and Proc_Name=flow.Proc_Name
                             and Test_Time>To_Date(p_BegDate,'YYYY-MM-DD') and Test_Time<To_Date(p_BegDate,'YYYY-MM-DD')+p_Hours/24;
                       end if;
                       --更新上一站的结束时间
                        Update tb_LineProcTime_new t1
                        SET t1.NextProctime=(Select t2.Test_Time from tb_LineProcTime_new t2 where t2.Proc_Name=flow.Proc_Name AND t2.SN=v_CellName)
                        where SN=v_CellName and Proc_name=v_ProcName; 
                elsif flow.Proc_Name='EXT-LINK' then  --BIS_EXTCODE_LINK
                       Select Count(EXT_CODE) into v_ParentSNCount from BIS_EXTCODE_LINK where CELL_NAME=v_CellName and Update_Date>to_Date(p_BegDate,'YYYY-MM-DD') and Update_Date<To_Date(p_BegDate,'YYYY-MM-DD')+p_Hours/24;
                       exit when v_ParentSNCount=0;
                       Select EXT_CODE into v_ParentSN from BIS_EXTCODE_LINK where CELL_NAME=v_CellName and Update_Date>to_Date(p_BegDate,'YYYY-MM-DD') and Update_Date<To_Date(p_BegDate,'YYYY-MM-DD')+p_Hours/24;
                       --exit when v_ParentSN is null;
                       select Count(1) into v_rowcount from tb_LineProcTime_new where SN=v_ParentSN and Proc_Name=flow.Proc_Name ;
                       if v_rowcount=0 then
                         Insert into tb_LineProcTime_new(SN,Proc_Name,Test_Time,NextProcTime,PassTime,Line_No,PN,Flow_Type)
                         Select SN,Proc_Name,Test_Time,null NextProcName,null PassTime,Line_No,PN,Remark_1 Flow_Type
                             from NVT_PROCESS_STATUS 
                             where Test_Type=1 and Test_CNT=1 and RT_CNT=0 
                             and Line_No=p_LineNo
                             and SN=v_ParentSN
                             and Proc_Name=flow.Proc_Name
                             and Test_Time>To_Date(p_BegDate,'YYYY-MM-DD') and Test_Time<To_Date(p_BegDate,'YYYY-MM-DD')+p_Hours/24;
                       end if;
                       --更新上一站的结束时间
                        Update tb_LineProcTime_new t1
                        SET t1.NextProctime=(Select t2.Test_Time from tb_LineProcTime_new t2 where t2.Proc_Name=flow.Proc_Name AND t2.SN=v_ParentSN)
                        where SN=v_CellName and Proc_name=v_ProcName; 
                else
                       select Count(1) into v_rowcount from tb_LineProcTime_new where SN=v_CellName and Proc_Name=flow.Proc_Name;
                       if v_rowcount=0 then
                         Insert into tb_LineProcTime_new(SN,Proc_Name,Test_Time,NextProcTime,PassTime,Line_No,PN,Flow_Type)
                         Select SN,Proc_Name,Test_Time,null NextProcName,null PassTime,Line_No,PN,Remark_1 Flow_Type
                             from NVT_PROCESS_STATUS 
                             where Test_Type=1 and Test_CNT=1 and RT_CNT=0 
                             and Line_No=p_LineNo
                             and SN=v_CellName
                             and Proc_Name=flow.Proc_Name
                             and Test_Time>To_Date(p_BegDate,'YYYY-MM-DD') and Test_Time<To_Date(p_BegDate,'YYYY-MM-DD')+p_Hours/24;
                        end if;
                        --更新上一站的结束时间
                        Update tb_LineProcTime_new t1
                        SET t1.NextProctime=(Select t2.Test_Time from tb_LineProcTime_new t2 where t2.Proc_Name=flow.Proc_Name AND t2.SN=v_CellName)
                        where SN=v_CellName and Proc_name=v_ProcName; 
                end if;
                v_ProcName:=flow.proc_name;  --更新工序名变量
                v_CellName:=v_ParentSN;      --更新条码变量
            end loop;
          --Select * from NVT_CP_LIST_01 where PN='519110001435' and Flow_Type='方案一' and Test_Type=1;
          --select * from Nvt_Proc_Matchtb order by Proc_Name;
          /*Update tb_LineProctime t1  --更新下一站时间
            SET NextProcTime=(Select Test_Time from (Select rownum,Test_Time from tb_LineProctime t2 where SN=tb.SN
                                           and Proc_Name<>tb.proc_name
                                           and Test_Time>=tb.test_time
                                    order by Test_Time) where rownum=1)
           where t1.SN=tb.Sn--'518110001000-00000-05-21A28-10153' 
           and Proc_Name=tb.proc_name
           and Proc_Name=p_ProcName
           and t1.Test_Time=tb.test_time
           and EXISTS(Select Test_Time from (Select rownum,Test_Time from tb_LineProctime t2 where SN=tb.SN
                                           and Proc_Name<>tb.proc_name
                                           and Test_Time>=tb.test_time
                                    order by Test_Time) where rownum=1) ;*/
       end loop;
       
       update tb_LineProcTime_new SET PassTime=Round(To_Number(NextProcTime-Test_Time)*24*60*60)
        where /*Proc_Name=p_ProcName and*/ NextProcTime is not null and PassTime is null;
        
        
       for c in (Select SN,Proc_Name,Test_Time,NextProcTime,PassTime,Line_No,PN from tb_LineProcTime_new /*where Proc_Name=p_ProcName*/ order by SN,Test_Time,Proc_Name) loop
          
            v_procData.extend();
            v_procData(v_procData.count):=PROCRecord(c.SN,c.proc_name,c.Test_Time,c.NextProcTime,c.PassTime,c.Line_No,c.PN);
       end loop;
       commit;
       return v_procData;
     end fn_CalcLineProcTime_Nov;

    调用 : Select * from table(fn_CalcLineProcTime_Nov('A4305','2021-11-2',4));

  • 相关阅读:
    java web环境搭建
    java动手动脑异常处理
    java动手动脑多态
    python全栈开发day67--字段类型、字段属性、ORM回顾
    python全栈开发day66-视图系统、路由系统
    python全栈开发day65-templates:tags、母版和继承、组件、静态文件相关、simple_tag和inclusion_tag
    python全栈开发day64-模板-变量和(.)的使用,filters和自定义filter
    Django Models的数据类型汇总
    nginx反向代理uwsgi django服务器搭建总结
    Centos更新yum源
  • 原文地址:https://www.cnblogs.com/ldc218/p/15500066.html
Copyright © 2020-2023  润新知