Oracle- 存儲過程和異常捕捉

  這段時間晚上有時候去打打球,回家看看電視劇,日子一每天過……。學了點ORACLE存儲過程基礎,做一下備註,以便往後需查閱。java

 

建立無參存儲過程sql

create procedure p_myPro1 is
begin
  insert into dept(deptno,dname,loc) values(60,'ccx','321321');
end;

修改無參存儲過程oracle

create or replace procedure p_myPro1 is
begin
  insert into dept(deptno,dname,loc) values(60,'ccx','321321'); 
end;

建立和修改有參存儲過程ide

create or replace procedure p_myPro2(spName varchar2,newSal number) is
begin
    update emp set sal=newSal where ename=spName;
end;


call p_myPro2('SCOTT','1111');

建立和修改有參存儲過程 帶反回值工具

create or replace function f_myPro3(spName varchar2)
return number is
yearSal number(7,2);
begin
  select sal*12 into yearSal from emp where ename=spName;
  return yearSal;
end;

調用方法:select f_mypro3('SCOTT') from dual;spa

 

查看錯誤信息
 show error;code

調用存儲過程
調用存儲過程的方式有兩種,call,execserver

exec是sqlplus的命令,只能在sqlplus中使用。和 set serveroutput on 一塊兒用。call是sql命令,任何工具均可以使用。對象

例如:call p_myPro1() blog

Oracle輸出語句過程

dbms_output是oracle所提供的包(相似java的開發包),該包包含一些過程,put_line就是dbms_output包的一個過程。

Oracle變量的使用例子 

declare
v_ename varchar2(5);
v_sal number(7,2);
begin
  select ename,sal into v_ename,v_sal from emp where empno=7369;
  dbms_output.put_line('姓名'||v_ename||'   工資'||v_sal);
end;

Oracle異常捕捉

declare
v_ename varchar2(5);
v_sal number(7,2);
begin
  select ename,sal into v_ename,v_sal from emp where empno=1111;
  dbms_output.put_line('姓名'||v_ename||'   工資'||v_sal);
  
  exception
  when no_data_found then
    dbms_output.put_line('SELECT INTO沒有找到數據');
  when not_logged_on then
    dbms_output.put_line('沒有鏈接到ORACLE');
  
end;

 

錯誤號

異常錯誤信息名稱

說明

ORA-0001

Dup_val_on_index

違反了惟一性限制

ORA-0051

Timeout-on-resource

在等待資源時發生超時

ORA-0061

Transaction-backed-out

因爲發生死鎖事務被撤消

ORA-1001

Invalid-CURSOR

試圖使用一個無效的遊標

ORA-1012

Not-logged-on

沒有鏈接到ORACLE

ORA-1017

Login-denied

無效的用戶名/口令

ORA-1403

No_data_found

SELECT INTO沒有找到數據

ORA-1422

Too_many_rows

SELECT INTO 返回多行

ORA-1476

Zero-divide

試圖被零除

ORA-1722

Invalid-NUMBER

轉換一個數字失敗

ORA-6500

Storage-error

內存不夠引起的內部錯誤

ORA-6501

Program-error

內部錯誤

ORA-6502

Value-error

轉換或截斷錯誤

ORA-6504

Rowtype-mismatch

宿主遊標變量與 PL/SQL變量有不兼容行類型

ORA-6511

CURSOR-already-OPEN

試圖打開一個已處於打開狀態的遊標

ORA-6530

Access-INTO-null

試圖爲null 對象的屬性賦值

ORA-6531

Collection-is-null

試圖將Exists 之外的集合( collection)方法應用於一個null pl/sql 表上或varray

ORA-6532

Subscript-outside-limit

對嵌套或varray索引得引用超出聲明範圍之外

ORA-6533

Subscript-beyond-count

對嵌套或varray 索引得引用大於集合中元素的個數.

    

對這種異常狀況的處理,只需在PL/SQL塊的異常處理部分,直接引用相應的異常狀況名,並對其完成相應的異常錯誤處理便可。

 

 

看存儲過程示例:

這裏經過IM_INSTOCK_D0.LOCNO%TYPE 取得表的類型

 is下面的存儲過程的變量,()裏面是存儲過程的參數

 

create or replace procedure P_IM_INSTOCK_M_AUDIT_LINE
(
       as_LOCNO             IM_INSTOCK_D0.LOCNO%TYPE,                   --倉別
       as_OWNER_NO          IM_INSTOCK_D0.OWNER_NO%TYPE,                --委託業主
       as_SHEET_ID          IM_INSTOCK_D0.SHEET_ID%TYPE,                --上架單號
       as_SEQ_ID            IM_INSTOCK_D0.SEQ_ID%TYPE,                  --上架單內序號
       as_INSTOCK_WORKER    IM_INSTOCK_D0.UPDT_NAME%TYPE,               --上架人員
       as_TerminalFlag      container_content_move.terminal_flag%type,  --做業設備
       as_strMsg            out varchar2                                --錯誤信息返回
)
is


  ls_IMPORT_NO              IM_INSTOCK_D0.IMPORT_NO%TYPE;
  ls_CONTAINER_NO           IM_INSTOCK_D0.CONTAINER_NO%TYPE;
  ls_CELL_NO                IM_INSTOCK_D0.DEST_CELL_NO%type;   --源架儲位
  ls_CELL_ID                IM_INSTOCK_D0.DEST_CELL_ID%type;   --源架儲位ID
  ls_DEST_CELL_NO           IM_INSTOCK_D0.DEST_CELL_NO%type;   --預上架儲位
  ls_DEST_CELL_ID           IM_INSTOCK_D0.DEST_CELL_ID%type;   --預上架儲位ID
  ls_DEST_QTY               IM_INSTOCK_D0.DEST_QTY%type;       --預上架數量
  ls_REAL_CELL_NO           IM_INSTOCK_D0.REAL_CELL_NO%type;   --實際上架儲位
  ls_REAL_CELL_ID           IM_INSTOCK_D0.REAL_CELL_ID%type;   --實際上架儲位ID
  ls_REAL_QTY               IM_INSTOCK_D0.REAL_QTY%type;       --實際上架數量
  ls_Article_NO             IM_INSTOCK_D0.ARTICLE_NO%TYPE;
  li_Article_ID             IM_INSTOCK_D0.ARTICLE_ID%TYPE;
  ls_DepID                  IM_INSTOCK_M0.dept_id%type;
  ls_Lot_No                 IM_INSTOCK_D0.Lot_No%type;
  ls_errMsg                 varchar2(200);                     --錯誤信息
  li_RowCount               int;
  li_MixFlag                cm_defcell.mix_flag%TYPE;
  li_MixBatch               cm_defcell.mix_batch%TYPE;
  ls_CellStatus             cm_defcell.cell_status%TYPE;
  ls_CellCheckStatus        cm_defcell.check_status%TYPE;
  ld_ProduceDate            CONTAINER_ARTICLE_INFO.PRODUCE_DATE%TYPE;
  ls_o_type                 cm_defarea.o_type%type;

  ls_AREA_HABITUDE          CM_DEFAREA.AREA_HABITUDE%type;
  ls_BUFFER_FLAG            CM_DEFAREA.BUFFER_FLAG%type;

  ls_ERROR          exception;                         --異常

begin


   --鎖定當前表的行
   update im_instock_d0  set status=status
   where LOCNO=as_LOCNO and OWNER_NO=as_OWNER_NO and SHEET_ID=as_SHEET_ID and SEQ_ID=as_SEQ_ID and status in ('10','11');

   IF SQL%ROWCOUNT=0 THEN
      ls_errMsg:='更新此單失敗';
      raise ls_ERROR;
   END IF;



  select IMD.CELL_NO,IMD.CELL_ID,DEST_CELL_NO,DEST_CELL_ID,DEST_QTY,REAL_CELL_NO,REAL_CELL_ID,REAL_QTY,IMD.CONTAINER_NO,
    IMD.ARTICLE_NO,IMD.ARTICLE_ID,IMD.DEPT_ID,IMD.LOT_NO,IMD.IMPORT_NO
    into ls_CELL_NO,ls_CELL_ID, ls_DEST_CELL_NO,ls_DEST_CELL_ID,ls_DEST_QTY,ls_REAL_CELL_NO,ls_REAL_CELL_ID,ls_REAL_QTY,
    ls_CONTAINER_NO,ls_Article_NO,li_Article_ID,ls_DepID,ls_Lot_No,ls_IMPORT_NO
    from IM_INSTOCK_D0 IMD,IM_INSTOCK_M0 IMM
   where IMD.LOCNO=IMM.LOCNO AND IMD.OWNER_NO=IMM.OWNER_NO AND
     IMD.SHEET_ID=IMM.SHEET_ID AND IMD.LOCNO=as_LOCNO and IMD.OWNER_NO=as_OWNER_NO
     and IMD.SHEET_ID=as_SHEET_ID and IMD.SEQ_ID=as_SEQ_ID;

   IF ls_DEST_CELL_NO <> ls_REAL_CELL_NO THEN
      BEGIN
          select MIX_FLAG,MIX_BATCH,CELL_STATUS,CHECK_STATUS
          into li_MixFlag,li_MixBatch,ls_CellStatus,ls_CellCheckStatus
          from cm_defcell
          where cell_no=ls_REAL_CELL_NO;
          EXCEPTION WHEN NO_DATA_FOUND THEN
             ls_errMsg   :=ls_REAL_CELL_NO||'儲位不存在';
             raise ls_ERROR;
      END;
      if ls_CellStatus <> '0' then
          ls_errMsg   :=ls_REAL_CELL_NO||'儲位不可用嗎,沒法上架';
          raise ls_ERROR;
      end if;
      if ls_CellCheckStatus <> '0' then
          ls_errMsg   :=ls_REAL_CELL_NO||'在盤點中,沒法上架';
          raise ls_ERROR;
      end if;

      IF li_MixFlag = '0' THEN
         select count(1) into li_RowCount
         from container_content t1
         where t1.locno=as_LOCNO and t1.cell_no = ls_REAL_CELL_NO
           and ARTICLE_NO <> ls_Article_NO;
         IF li_RowCount > 0 THEN
             ls_errMsg   :=ls_REAL_CELL_NO||'儲位爲不可混載儲位,請從新指定儲位上架';
             raise ls_ERROR;
         END IF;
      END IF;

      IF li_MixBatch = '0' THEN
         select produce_date into ld_ProduceDate
         from container_article_info
         where article_id = li_Article_ID;

         select count(1) into li_RowCount
         from container_content t1
         where t1.locno=as_LOCNO and t1.cell_no = ls_REAL_CELL_NO
           and ARTICLE_NO = ls_Article_NO
           and not exists(select 1 from container_article_info t2
                          where t1.article_id=t2.article_id and t2.produce_date = ld_ProduceDate);
         IF li_RowCount > 0 THEN
             ls_errMsg   :=ls_REAL_CELL_NO||'儲位爲不可混批儲位,請從新指定儲位上架';
             raise ls_ERROR;
         END IF;
      END IF;

   END IF;


  update cm_defcell set cell_status=cell_status where cell_no=ls_REAL_CELL_NO and cell_status=0
         and check_status=0;

  if SQL%ROWCOUNT=0 then
     ls_errMsg:=ls_REAL_CELL_NO||'儲位不存在或不可用';
     raise ls_ERROR;
  end if;

  begin
      select t1.AREA_HABITUDE,t1.BUFFER_FLAG,t1.o_type into ls_AREA_HABITUDE,ls_BUFFER_FLAG,ls_o_type
      from CM_DEFAREA t1,CM_DEFCELL t2
       where t1.locno=t2.locno and t1.ware_no=t2.ware_no and t1.area_no=t2.area_no
         and t2.locno=as_locno and t2.cell_no=ls_REAL_CELL_NO;

      IF  ls_AREA_HABITUDE ='7' THEN
         ls_errMsg:=ls_REAL_CELL_NO||'所在儲區爲異常區,請覈實';
         raise ls_ERROR;
      END IF;

      if  ls_BUFFER_FLAG<>'0' then
         ls_errMsg:=ls_REAL_CELL_NO||'不是做業區';
         raise ls_ERROR;
      end if;

      if (ls_AREA_HABITUDE<>'1' and ls_AREA_HABITUDE<>'20' and  ls_AREA_HABITUDE<>'6')  then
         ls_errMsg:=ls_REAL_CELL_NO||'不是良品區或限制出貨區';
         raise ls_ERROR;
      end if;

  end;


   P_BS_StockChangeLog(as_LOCNO,as_OWNER_NO,as_SHEET_ID,'100',ls_CELL_NO,ls_CELL_ID,ls_REAL_CELL_NO,ls_REAL_CELL_ID,
        ls_DepID,ls_Lot_No,ls_Article_NO,li_Article_ID,ls_REAL_QTY,as_INSTOCK_WORKER,as_TerminalFlag);


    if ls_DEST_CELL_NO<>ls_REAL_CELL_NO then

        P_BS_StockBackRevServ(as_LOCNO,as_OWNER_NO,ls_CELL_NO,ls_CELL_ID,ls_DEST_CELL_NO,ls_DEST_CELL_ID,ls_DEST_QTY,0,ls_DepID,as_INSTOCK_WORKER,as_strMsg);
        if substr(as_strMsg,1,1)='N' then
           ls_errMsg:='修改庫存失敗'|| SUBSTR(as_strMsg,3);
           raise ls_ERROR;
        end if;

        P_BS_StockChangePal(as_LOCNO,as_OWNER_NO,ls_CELL_NO,ls_CELL_ID, ls_REAL_CELL_NO,-1,ls_CONTAINER_NO,ls_DepID, ls_REAL_QTY,as_INSTOCK_WORKER,0,ls_REAL_CELL_ID,as_strMsg );

        if substr(as_strMsg,1,1)='N' then
           ls_errMsg:='轉移庫存失敗'|| SUBSTR(as_strMsg,3);
           raise ls_ERROR;
        end if;

        update im_instock_d0 d set d.status='13',d.real_cell_id=ls_REAL_CELL_ID,d.Updt_Name=as_INSTOCK_WORKER,
           d.Updt_Date=sysdate where LOCNO=as_LOCNO and OWNER_NO=as_OWNER_NO
           and SHEET_ID=as_SHEET_ID and SEQ_ID=as_SEQ_ID;


    else

        P_BS_StockBackRevServ(as_LOCNO,as_OWNER_NO,ls_CELL_NO,ls_CELL_ID,ls_DEST_CELL_NO,ls_DEST_CELL_ID,ls_DEST_QTY,ls_REAL_QTY,ls_DepID,as_INSTOCK_WORKER,as_strMsg);

        if substr(as_strMsg,1,1)='N' then
           ls_errMsg:='修改庫存失敗' || SUBSTR(as_strMsg,3);
           raise ls_ERROR;
        end if;

        IF as_TerminalFlag=1 THEN   ---表單
            update im_instock_d0 d set d.status='13',d.real_cell_id=d.dest_cell_id
             where LOCNO=as_LOCNO and OWNER_NO=as_OWNER_NO
               and SHEET_ID=as_SHEET_ID and SEQ_ID=as_SEQ_ID;
        ELSE
            update im_instock_d0 d set d.status='13',d.real_cell_id=d.dest_cell_id,
               d.Updt_Name=as_INSTOCK_WORKER,  d.Updt_Date=sysdate
                where LOCNO=as_LOCNO and OWNER_NO=as_OWNER_NO
                 and SHEET_ID=as_SHEET_ID and SEQ_ID=as_SEQ_ID;
        END IF;
    end if;

    P_BS_StockChangeListLog(as_LocNo,as_OWNER_NO,ls_DepID,ls_Article_NO,li_Article_ID,ls_Lot_No,ls_REAL_QTY,'100','N');
/*    P_CONTENTER_LOTNO(as_LOCNO,as_OWNER_NO,'100',ls_IMPORT_NO,ls_Article_NO,li_Article_ID,'N',0,ls_Lot_No,ls_REAL_QTY,0,as_INSTOCK_WORKER,as_strMsg);
    if substr(as_strMsg,1,1)='N' then
       raise ls_ERROR;
    end if;
*/
    update bm_article_pcs bm set bm.recent_cell=ls_REAL_CELL_NO,bm.recent_pickcell=
    case when ls_o_type='P' then bm.recent_pickcell else ls_REAL_CELL_NO end where  bm.OWNER_NO=as_OWNER_NO and bm.article_no=ls_Article_NO;

   ----更新標籤表的狀態
     UPDATE CONTAINER_LABEL_M0 SET STATUS='13' WHERE CONTAINER_NO=ls_CONTAINER_NO  AND NOT EXISTS
     (SELECT 1 FROM im_instock_d0 WHERE CONTAINER_NO=ls_CONTAINER_NO AND STATUS<'13');

     IF SQL%ROWCOUNT<>0 THEN

        P_TRANS_CONTAINER_LABEL(as_locno,as_owner_no,ls_CONTAINER_NO,ls_errMsg);

         if substr(ls_errMsg,1,1)<>'Y' then
               ls_errMsg:=SUBSTR(ls_errMsg,3);
               raise ls_ERROR;
         end if;

     END IF;


      --導入頭檔
     insert into IM_INSTOCK_M(LOCNO, OWNER_NO, SHEET_ID, SHEET_TYPE,SHEET_DATE,DEPT_ID, AUTO_LOCATE_FLAG, ASSIGN_WORKER, ASSIGN_DATE,
                              REAL_WORKER, OPERATE_TYPE, STATUS, PRINT_TIMES, PRT_MEMO, BILL_MEMO,
                              AC_NO, RGST_NAME, RGST_DATE, UPDT_NAME, UPDT_DATE)
          select LOCNO, OWNER_NO, SHEET_ID, SHEET_TYPE, SHEET_DATE, DEPT_ID, AUTO_LOCATE_FLAG, ASSIGN_WORKER, ASSIGN_DATE,
                 REAL_WORKER, OPERATE_TYPE,'13' as STATUS, PRINT_TIMES, PRT_MEMO, BILL_MEMO,
                 SEQ_EOSBILL.NEXTVAL,RGST_NAME, RGST_DATE, UPDT_NAME, UPDT_DATE
            from IM_INSTOCK_M0
           where LOCNO=as_LOCNO and OWNER_NO=as_OWNER_NO and SHEET_ID=as_SHEET_ID
             and not exists(select 'X' from IM_INSTOCK_d0
                            where LOCNO=as_LOCNO and OWNER_NO=as_OWNER_NO and SHEET_ID=as_SHEET_ID
                              and status<>'13');
     if SQL%ROWCOUNT<>0 then

        delete from IM_INSTOCK_M0 where LOCNO=as_LOCNO and OWNER_NO=as_OWNER_NO and SHEET_ID=as_SHEET_ID;

        --導入明細表
        insert into IM_INSTOCK_D(LOCNO, OWNER_NO, SHEET_ID, SEQ_ID, CELL_NO, CELL_ID, CONTAINER_NO,
                              ARTICLE_NO, ARTICLE_ID, LOT_NO, SUPPLIER_NO,DEST_CELL_NO,DEST_CELL_ID, DEST_CONTAINER_NO,DEST_QTY,
                              REAL_CELL_NO, REAL_CELL_ID, REAL_CONTAINER_NO, REAL_QTY, IMPORT_NO, IMPORTSUM_NO, CHECK_NO,
                              WORKLOAD_P, WORKLOAD_C, WORKLOAD_B, STATUS,ROW_FLAG,LABEL_NO,DEPT_ID,UPDT_NAME,UPDT_DATE)
          select LOCNO, OWNER_NO, SHEET_ID, SEQ_ID, CELL_NO, CELL_ID, CONTAINER_NO, ARTICLE_NO,
                 ARTICLE_ID, LOT_NO,SUPPLIER_NO, DEST_CELL_NO,DEST_CELL_ID, DEST_CONTAINER_NO,DEST_QTY, REAL_CELL_NO, REAL_CELL_ID,
                 REAL_CONTAINER_NO, REAL_QTY, IMPORT_NO, IMPORTSUM_NO, CHECK_NO, WORKLOAD_P, WORKLOAD_C, WORKLOAD_B,
                 '13' as STATUS,ROW_FLAG,LABEL_NO,DEPT_ID,UPDT_NAME,UPDT_DATE
            from IM_INSTOCK_D0
           where LOCNO=as_LOCNO and OWNER_NO=as_OWNER_NO and   SHEET_ID=as_SHEET_ID ;
     if SQL%ROWCOUNT<>0 then
        delete from IM_INSTOCK_D0 where LOCNO=as_LOCNO and OWNER_NO=as_OWNER_NO and SHEET_ID=as_SHEET_ID;
     end if;
   end if;

   as_strMsg:='Y|成功';
--異常處理
exception
   WHEN ls_ERROR THEN
        as_strMsg:='N|'||ls_errMsg;
   when others then
        as_strMsg:='N|' || to_char(SQLCODE) || '      ' || SUBSTR(SQLERRM, 1, 100);
end P_IM_INSTOCK_M_AUDIT_LINE;
相關文章
相關標籤/搜索