【问题标题】:How to run Oracle function which returns more than one value如何运行返回多个值的Oracle函数
【发布时间】:2017-05-08 10:41:18
【问题描述】:

我的测试函数是这个

CREATE OR REPLACE FUNCTION MULTI_VAL
(MYNAME OUT EMP2017.ENAME%TYPE)
RETURN NUMBER AS
  MYSAL EMP2017.SAL%TYPE;
BEGIN
  SELECT SAL, ENAME INTO MYSAL, MYNAME FROM EMP2017 ;
  RETURN MYSAL;
END;
/

当我像运行它时

variable mynm varchar2(20)

SELECT MULTI_VAL(:mynm) FROM dual;

它给出了这个错误

第 1 行出现错误:
ORA-06553: PLS-561: 参数 'MYNAME' 值的字符集不匹配

【问题讨论】:

  • 那么EMP2017.MYNAME的数据类型是什么?
  • 假设是nvarchar2(20),你的数据库和国家字符集是什么?此外,我希望该查询获得ORA-06572: Function MULTI_VAL has out arguments,并且由于该函数的查询没有过滤器,因此如果表中没有一行,它将出错。你真正想做什么?也许你想返回一个引用游标或一个流水线集合?

标签: oracle function plsql


【解决方案1】:

您现在得到的错误表明数据类型不匹配。

但是,您的代码存在一个根本问题。我们不能在 SQL 中使用具有 OUT 参数的函数。因此,一旦您修复了数据类型问题,您将收到此错误:ORA-06572: Function MULTI_VAL has out arguments

你可以这样运行它:

declare
    n varchar2(20);
    x number;
begin
    x := multi_val(n);
end;
/

通常,带有 OUT 参数的函数被认为是不好的做法。语法允许它们,但用法很难理解。最好使用带有两个 OUT 参数的过程(因为无论如何我们只能在 PL/SQL 中调用该程序)或者让函数返回用户定义的类型。

【讨论】:

    【解决方案2】:
    CREATE TABLE EMP2017(ENAME VARCHAR2(10),SAL NUMBER);
    
    INSERT INTO EMP2017 VALUES ('SMITH',5000);
    INSERT INTO EMP2017 VALUES ('JOHNS',1000);
    
    COMMIT;
    
    CREATE  TYPE RET_MULT AS OBJECT 
    (ENAME     VARCHAR2(10),SAL NUMBER); 
    
    CREATE TYPE T_RET_MULT AS TABLE OF RET_MULT;
    
    CREATE OR REPLACE FUNCTION MULTI_VAL RETURN T_RET_MULT PIPELINED IS 
     MYSAL  RET_MULT;
    BEGIN
    FOR I IN(SELECT SAL, ENAME FROM EMP2017) LOOP
      MYSAL := RET_MULT(I.ENAME,I.SAL);
      PIPE ROW(MYSAL);
    END LOOP ;
    RETURN ;
    END;
    
    SELECT * FROM TABLE(MULTI_VAL());
    

    【讨论】:

    • 为什么在这个任务中使用管道功能?有必要吗?
    • 在该解决方案中,您可以获得多列和多行
    • 我看到了,但它可以在没有流水线的情况下完成。
    • 是的,可能,这是另一种解决方案,它们中的哪一个最适合它可以使用。表函数也可以用作 select 语句的一部分,如果您使用并行选项执行语句,此解决方案支持该功能
    【解决方案3】:

    我认为这个问题可以不使用管道函数来解决。像这样。除功能外,所有预先需要的数据都与@Sedat.Turan 所述相同。抱歉复制/过去。

    CREATE TABLE EMP2017(ENAME VARCHAR2(10),SAL NUMBER);
    
    INSERT INTO EMP2017 VALUES ('SMITH',5000);
    INSERT INTO EMP2017 VALUES ('JOHNS',1000);
    
    COMMIT;
    
    CREATE  TYPE RET_MULT AS OBJECT 
    (ENAME     VARCHAR2(10),SAL NUMBER); 
    
    CREATE TYPE T_RET_MULT AS TABLE OF RET_MULT;
        create or replace function MULTI_VAL return T_RET_MULT is
           RET_SET T_RET_MULT;
        begin
    
           select RET_MULT(ENAME, SAL) bulk collect into RET_SET from EMP2017;
    
           return RET_SET;
        end;
    

    【讨论】:

    • 你说得对,流水线功能不是必需的,但是这两种解决方案都假定原始问题中没有的东西。
    • 你为什么这么认为?我认为这个解决方案正是所有者想要的问题。根据问题,我认为正确的答案不会是解决错误。 select语句没有条件,而且我认为一次不会只有一行,所以给出的答案更适合这个问题。
    猜你喜欢
    • 1970-01-01
    • 2012-06-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-17
    • 2017-07-07
    相关资源
    最近更新 更多