如何运行返回多个值的Oracle函数
Posted
技术标签:
【中文标题】如何运行返回多个值的Oracle函数【英文标题】:How to run Oracle function which returns more than one value 【发布时间】: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
,并且由于该函数的查询没有过滤器,因此如果表中没有一行,它将出错。你真正想做什么?也许你想返回一个引用游标或一个流水线集合?
【参考方案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语句没有条件,而且我认为一次不会只有一行,所以给出的答案更适合这个问题。以上是关于如何运行返回多个值的Oracle函数的主要内容,如果未能解决你的问题,请参考以下文章
Oracle:如何为“SELECT * FROM tab WHERE name IN (function())”创建返回值的函数