Oracle函数返回varchar2没问题,但返回SYS_REFCURSOR得到ORA-14551

时间:2016-07-18 09:25:30

标签: oracle

工具:Toad 9.7.2.5

我写了一个函数,里面有一个insert语句。

我执行命令

SELECT TWO2F_QUERY_TEST ('XX', 'XX') 
  FROM DUAL;

当这个函数返回SYS_REFCURSOR时,我会得到

  

1,N,* INSERT TWO2R063_W1错误(C1-NOT USED)** ORA-14551:不能   在查询中执行DML操作

当此函数返回varchar2时,它将处理成功的

代码:

CREATE OR REPLACE FUNCTION TWO2F_QUERY_TEST
(PI_BUS_ID         IN  VARCHAR2 ,
 PI_TMNL_ID        IN  VARCHAR2 
)RETURN SYS_REFCURSOR IS
--)RETURN VARCHAR2 IS
PO_CURSOR SYS_REFCURSOR;
WK_ACTION VARCHAR2(01) := 'Y';
WK_MSG    VARCHAR2(100);
BEGIN
  BEGIN
    INSERT INTO TWO2R063_W1
      ( R063W1_TITLE   ,
        R063W1_FORWARD
      )
    VALUES             
      ( 'PROGRAM NOT USED' ,
        'XX'            
      )
    ;
  EXCEPTION
    WHEN OTHERS THEN
      WK_ACTION := 'N';
      WK_MSG    := SUBSTR('*INSERT TWO2R063_W1 ERROR(C1-NOT USED)'||SQLERRM, 1, 100);
      GOTO OUTER;
  <<OUTER>> 
  <<ENDRTN>>                                   

  OPEN PO_CURSOR FOR 
    SELECT ROWNUM    AS PO_ROWNUM ,
           WK_ACTION AS PO_ACTION , 
           WK_MSG    AS PO_MSG   
      FROM DUAL
    ;

  RETURN PO_CURSOR;

  --RETURN 'Y';

END TWO2F_QUERY_TEST;

/
SHOW ERROR;
DROP    PUBLIC  SYNONYM TWO2F_QUERY_TEST;
CREATE  PUBLIC  SYNONYM TWO2F_QUERY_TEST FOR TWO2F_QUERY_TEST;
GRANT   EXECUTE ON TWO2F_QUERY_TEST TO GTS_AP_MAINTAIN, EGTS;
/

========================================================
DROP TABLE TWO2.TWO2R063_W1 CASCADE CONSTRAINTS;

CREATE GLOBAL TEMPORARY TABLE TWO2.TWO2R063_W1
(R063W1_TITLE   VARCHAR2(50 BYTE),
 R063W1_FORWARD VARCHAR2(20 BYTE)
)ON COMMIT PRESERVE ROWS NOCACHE;

DROP PUBLIC SYNONYM TWO2R063_W1;
CREATE PUBLIC SYNONYM TWO2R063_W1 FOR TWO2.TWO2R063_W1;
GRANT DELETE, INSERT, SELECT, UPDATE ON TWO2.TWO2R063_W1 TO TWO2_MAINTAIN;
GRANT SELECT ON TWO2.TWO2R063_W1 TO TWO2_QUERY;

2 个答案:

答案 0 :(得分:0)

在您的第一个pragma autonomous_transaction关键字结束之前声明begin并查看。

示例

  CREATE OR REPLACE FUNCTION TWO2F_QUERY_TEST
       (PI_BUS_ID         IN  VARCHAR2 ,
        PI_TMNL_ID        IN  VARCHAR2 
       )RETURN SYS_REFCURSOR IS
      --)RETURN VARCHAR2 IS
       PO_CURSOR SYS_REFCURSOR;
       WK_ACTION VARCHAR2(01) := 'Y';
       WK_MSG    VARCHAR2(100);

        PRAGMA AUTONOMOUS_TRANSACTION;
        BEGIN
        -- Your code to insert
        END

答案 1 :(得分:0)

我认为问题在于你是在SELECT中调用函数而不是在返回类型中。现在就删除DML并测试它。 这是我的测试:

CREATE OR REPLACE FUNCTION TWO2F_QUERY_TEST
RETURN SYS_REFCURSOR IS
PO_CURSOR SYS_REFCURSOR;
BEGIN

  OPEN PO_CURSOR FOR 
    SELECT ROWNUM        AS PO_ROWNUM ,
           owner         AS PO_ACTION , 
           table_name    AS PO_MSG   
      FROM all_tables
    ;

  RETURN PO_CURSOR;
END TWO2F_QUERY_TEST;
/


declare 
  cur  SYS_REFCURSOR;
  l_rownum number; 
  l_action varchar2(30);
  l_msg    varchar2(30);
begin
  cur := TWO2F_QUERY_TEST;
  fetch cur into l_rownum, l_action, l_msg;
  close cur;
  dbms_output.put_line(l_rownum||') '||l_action||'.'||l_msg); 
end;
/

这是我的输出:

1) SYS.DUAL

您的问题是从SQL调用DML。您有以下选择:

1)删除DML

2)不要从SQL调用函数

3)如果可能的话,将DML包装成自治事务。