Oracle 11g - 如何在其中调用带有DML的函数?

时间:2015-09-22 07:33:12

标签: java oracle function plsql oracle11g

我做了一个类似......的功能。

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;

我有两个问题

  1. 如何将此功能称为测试?
  2. 是否可以在exception声明中返回值?
  3. 关注代码是我想要实现的(我用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;
        }
    

    关于代码的条件。

    • 无论如何必须返回(成功与否)
    • 必须更新,是否插入成功

    我很抱歉java代码,但这是我能解释得最好的。谢谢你的回答。 B'/ P>

    ========编辑

    抱歉,我没有告诉我失败了。 (来自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
    3. =================编辑#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

      我陷入了两难境地,一个函数导致错误,一个程序无法返回。 我需要更好的解决方案。

      我想要的目标是

      • 远程数据库将调用我的函数,我需要返回响应代码。
      • 在此功能中,我必须插入并更新表格。

      由于

2 个答案:

答案 0 :(得分:2)

是和是:)

为了测试一个函数你可以1.将它作为数据库对象保存在一个包中。或者您可以使用工作台中的execute或exec关键字运行它(我通常在SQL开发人员中执行此操作)

(PWLSQL)您始终可以使用return关键字在异常块中返回值。

(JAVA)您可以编写自己的类,该类继承自异常类,并编写自己的返回特定值的方法。

我希望这会有所帮助。

答案 1 :(得分:0)

我不能说我解决了这个问题,但我找到了一些东西。当我在sqlplus中运行时,不会发生ORA-14552错误。该错误仅发生在sql developer。

以下是我在SQLPlus(终端)中运行它的方法

    SQL> var tmp varchar2(2);                          -- define a variable
    SQL> execute :tmp := PILE_DATA@DB_LINK('a', 1, 2); -- set value to variable
    SQL> print tmp;                                    -- print the result for checking

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

其他选项是创建一个处理Exception的包装函数。

即。创建一个没有Exception处理的函数,如下所示。

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; 

构建一个处理Exception的包装类

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;

这就是我在最后一次避免这个错误的方法。