2015-09-22 35 views
2

我做了一個功能像...Oracle 11g - 如何在DML中調用一個函數?

create or replace function 
    pile_data 
    (v_id IN NUMBER, v_area IN VARCHAR2, v_cust_id IN NUMBER) 
    return VARCHAR2 
AS 
    rs VARCHAR2(2); 
    cur_id NUMBER; 
    -- PRAGMA AUTONOMOUS_TRANSACTION; 
BEGIN 
    select if_seq.currVal into cur_id from dual; 
    select '00' into rs from dual; 
    insert into IF_WORK 
    (id, area, cust_id, rc) 
    values 
    (if_tx_seq.nextVal, v_area, v_cust_id, rs); 
    update IF_WORK set rc=rs where id = cur_id; 
    return rs; 
    exception 
    when dup_val_on_index then 
     select '01' into rs from dual; 
    return rs; 
end; 

而且我有2個問題

  1. 如何調用該函數的測試?
  2. 是否有可能在exception聲明中返回值?

跟蹤代碼是我想要實現(我用java做,但有PLSQL實現)

public String pile_data(String ... params){ 
     String rs = "00"; 
     int cur_id = SEQ.currVal; 
     try{ 
      insert(params); 
     }catch(Exception ex){ 
      //HANDLING ERRORS 
      String exceptionName = ex.getClass().getName(); 
      switch (exceptionName) { 
      case "KEY_DUPLICATION": 
       rs = "01"; 
       break; 
      case "CONNECTION_TIMEOUT": 
       rs = "02"; 
       break; 
      default: 
       rollback(); 
       rs = "99"; 
       break; 
      } 
     }finally{ 
      // UPDATE ORIGINAL TABLE 
      update(cur_id, rs); 
     } 
     return rs; 
    } 

我對代碼的條件是什麼。

  • 不得不反正(成功或NOT)返回
  • 必須更新,是否插入成功與否

我對Java代碼抱歉,這是我能解釋最好。感謝您的回答。 b

========編輯

對不起,我沒有告訴我失敗了。 (來自Oracle的錯誤代碼,由我自己翻譯的消息)

  1. execute pile_data(params ...);。它返回這個錯誤ORA-06550 : it is not a procedure or not defined
  2. select pile_data(params) from dual;。它返回錯誤ORA-14552: Can not execute DDL, Commit, Rollback which is inside of Query or DML

=================編輯#2 ================

所以我現在正在嘗試將其更改爲具有返回值的過程。 但是,由於調用者需要獲得結果,所以我用函數包裝了。

create or replace procedure 
    pile_data 
    (params ... , rs OUT VARCHAR2) 
IS 
    cur_id NUMBER; 
BEGIN 
    select if_seq.currVal into cur_id from dual; 
    select '00' into rs from dual; 
    insert into IF_WORK 
    (target params ..., rc) 
    values 
     (params ..., rs); 
    update IF_WORK set rc=rs where tx_id = cur_id; 
    -- DBMS_OUTPUT.PUT_LINE(rs); -- it does not work 
    exception 
    when dup_val_on_index then 
     select '01' into rs from dual; 
     -- DBMS_OUTPUT.PUT_LINE(rs); 
    when others then 
     rollback; 
     select '99' into rs from dual; 
     -- DBMS_OUTPUT.PUT_LINE(rs); 
end; 


create or replace function pile_data_wrapper(params ...) 
return varchar2 
is 
    rs varchar2(2); 
begin 
    pile_data(params ... , rs); 
    return rs; 
end; 

select pile_data_wrapper(params ...) from dual; 

而我還得到了ORA-14552

我有一個困境,一個函數導致錯誤,並且程序無法返回。 我需要更好的解決方案。

我想我們的目標是低於

  • 遠程DB會打電話給我的功能,我需要返回響應代碼。
  • 在這個函數中我必須插入和更新一個表。

感謝

+0

據我所知,沒有辦法限制函數不允許發佈DML語句。你將需要改變你的函數到一個帶有'OUT'參數的程序以獲得返回值 –

+0

@a_horse_with_no_name感謝您的回答。但如果你不介意,你能否提出一個返回值的過程的例子?謝謝 –

回答

2

是的是:)

爲了測試一個功能,您可以1.它通過將其放置在包中保存爲一個數據庫對象。或者你可以在你的工作臺中使用execute或exec關鍵字來運行它(我通常在SQL開發者中這樣做)

(PWLSQL)你可以總是使用return關鍵字在異常塊中返回一個值。

(JAVA)你可以編寫你自己的繼承自異常類的類,並編寫你自己的返回特定值的方法。

我希望這會有所幫助。

+0

謝謝你的回答。我非常高興能夠在'exception'子句中返回值。就像你說的那樣,我把一個上面的一個作爲一個包裝,然後用'dual'選擇'select PKG_NAME.FUNC_NAME(params ...)。現在我有'ORA-14552'錯誤。我怎樣才能解決這個問題?幫我多一點:D –

+0

那麼ORA14552問題意味着你正在發佈一個提交或回滾程序中的一個點,它被阻止或不允許。如果我看看你的代碼,我發現你的編譯指示被評論了,你是否試圖通過使用「PRAGMA AUTONOMOUS_TRANSACTION;」使它成爲一個自治事務? ? –

+0

我不能說我解決了這個問題,但我找到了一些東西。當我在sqlplus中運行這個時,'ORA-14552'錯誤不會發生。該錯誤只發生在SQL開發人員。 –

0

我不能說我解決了這個問題,但是我找到了一些東西。當我在sqlplus中運行這個時,ORA-14552錯誤不會發生。該錯誤只發生在SQL開發人員。

後續是怎麼跑這在sqlplus(終端)

SQL> var tmp varchar2(2);       -- define a variable 
    SQL> execute :tmp := [email protected]_LINK('a', 1, 2); -- set value to variable 
    SQL> print tmp;         -- print the result for checking 

============================ ====================

其他選項是製作一個處理異常的包裝函數。

即無需如下處理異常就可以創建函數。

FUNCTION CREATEWITH(v_id IN NUMBER,v_value1 IN VARCHAR2,v_value2 IN NUMBER) 
return Number 
Is 
BEGIN 
    insert into DEVICE_BALJU(id, value1, value2) 
    values (v_id, v_value1, v_value2); 

return SQL%ROWCOUNT ; 
END CREATEWITH; 

,並建立一個包裝類處理異常

create or replace FUNCTION "FN_WRAPPER" (v_id IN VARCHAR2,v_value1 IN NUMBER,v_value2 IN NUMBER) 
RETURN Varchar2 
is 
    rs VARCHAR2(2); 
    tmp NUMBER; 
begin 
-- DBMS_OUTPUT.PUT_LINE('Hello!!!'); 
    rs := '00'; 
    tmp := createWith(v_id, v_value1, v_value2); 
    RETURN rs; 

    EXCEPTION 
     WHEN OTHERS THEN 
      rs := '99'; 
      RETURN rs; 
END; 

這是我如何避免在最後的這個錯誤。