zoukankan      html  css  js  c++  java
  • 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));

  • 相关阅读:
    leetcode 576. Out of Boundary Paths 、688. Knight Probability in Chessboard
    leetcode 129. Sum Root to Leaf Numbers
    leetcode 542. 01 Matrix 、663. Walls and Gates(lintcode) 、773. Sliding Puzzle 、803. Shortest Distance from All Buildings
    leetcode 402. Remove K Digits 、321. Create Maximum Number
    leetcode 139. Word Break 、140. Word Break II
    leetcode 329. Longest Increasing Path in a Matrix
    leetcode 334. Increasing Triplet Subsequence
    leetcode 403. Frog Jump
    android中webView加载H5,JS不能调用问题的解决
    通过nginx中转获取不到IP的问题解决
  • 原文地址:https://www.cnblogs.com/ldc218/p/15500066.html
Copyright © 2011-2022 走看看