【问题标题】:Return Multiple Values from Oracle Function从 Oracle 函数返回多个值
【发布时间】:2019-07-08 13:21:52
【问题描述】:

我想创建一个函数,它将多行返回到一个对象类型的表中。

我已经创建了一个对象和一个嵌套表对象,现在当我运行该函数时出现一个错误,提示

PL/SQL:忽略 SQL 语句 PL/SQL: ORA-00947: 没有足够的值

-- Object type creation
create or replace type test_object_sn as object
(
    column_1 varchar2(30),
    column_2 varchar2(30),
    column_3 number 
);


-- Table of object
create or replace type test_otable_sn as table of test_object_sn; 

-- function (where I get an error)
create or replace function load_test_object_sn
return test_otable_sn
as  
    details test_otable_sn;
begin
    with ad as (select 'a', 'b', 4   from dual
    union all 
    select 'r', '5', 3  from dual
    union all
    select 'g', 's', 3  from dual)
    select * into details from ad; 

    return details;
end;

我想让 test_otable_sn 表对象加载数据,然后通过我的 load_test_object_sn 函数使用 table() 函数查询它 例如select * from table(load_test_object_sn);

【问题讨论】:

    标签: sql oracle plsql set-returning-functions


    【解决方案1】:

    更新:

    你知道如何为我有一个 sql 的情况修改这个吗 要执行的字符串变量中包含的语句?

    是的,我们可以使用游标引用 (SYS_REFCURSOR) 和 OPEN/FETCH/CLOSE 来代替 CURSOR 和 CURSOR FOR LOOP。

    语法是 OPEN <cursor-reference> FOR <string-containing-sql-statement> 。见下文。

    CREATE OR REPLACE FUNCTION load_test_object_sn
    RETURN test_otable_sn
    AS  
      details test_otable_sn := test_otable_sn();
    
      -- Variable stores SQL statement for cursor
      l_sql CLOB :=
        q'[with ad as (
             select 'a' column_1, 'b' column_2, 4 column_3 from dual union all
             select 'r', '5', 3  from dual union all 
             select 'g', 's', 3  from dual
           )
           select *
             from ad]';
    
      -- Cursor reference allows us to open cursor for SQL statement above
      rc SYS_REFCURSOR;
    
      -- Define object instance to store each row fetched from the cursor
      l_obj test_object_sn := test_object_sn(NULL, NULL, NULL);
    
      i PLS_INTEGER := 1;
    BEGIN
    
      -- Explicitly open, fetch from, and close the cursor
      OPEN rc FOR l_sql;
      LOOP
        FETCH rc INTO l_obj.column_1, l_obj.column_2, l_obj.column_3;
        EXIT WHEN rc%NOTFOUND;
        details.extend();
        details(i) := test_object_sn(l_obj.column_1, l_obj.column_2, l_obj.column_3);
        i := i + 1;
      END LOOP;
      CLOSE rc;
    
      RETURN details;
    END;
    

    原答案:

    不幸的是,不能以这种方式将 SELECT * INTO 与集合一起使用,所以这里有另一种填充表的方法:

    create or replace function load_test_object_sn
    return test_otable_sn
    as  
        details test_otable_sn := test_otable_sn();
        cursor c_ad is
        with ad as (select 'a' column_1, 'b' column_2, 4 column_3   from dual
        union all 
        select 'r', '5', 3  from dual
        union all
        select 'g', 's', 3  from dual)
        select * from ad;
        i pls_integer := 1;
    
    begin
    
       for ad_rec in c_ad loop     
          details.extend();
          details(i) := test_object_sn(ad_rec.column_1, ad_rec.column_2, ad_rec.column_3);
          i := i + 1;
       end loop;
    
        return details;
    end;
    /
    

    输出:

    SQL> SELECT * FROM TABLE(load_test_object_sn);
    
    COLUMN_1   COLUMN_2     COLUMN_3
    ---------- ---------- ----------
    a          b                   4
    r          5                   3
    g          s                   3
    

    【讨论】:

    • 谢谢这个作品,你知道如何修改这个场景,我有一个包含在字符串变量中的sql语句来执行吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-06-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-01
    • 2022-01-12
    • 2017-06-07
    相关资源
    最近更新 更多