【问题标题】:How to return a table of records from a PLSQL function?如何从 PLSQL 函数返回记录表?
【发布时间】:2016-01-27 16:38:29
【问题描述】:

我有一个具有三个不同查询的函数。第一个查询返回 plsql 记录类型中的单个记录。第二个查询返回另一个单个值,第三个也返回一个不同的单个值。现在我想用这两个值附加第一条记录,并从我的函数中返回该新记录的表。我怎样才能做到这一点。

create or replace function test(p_actBillDat date) return <what should I    return> as
 type tab_accountNum is table of account.account_num%type;
 var_accountNum tab_accountNum;

 type query1Record is record(
 accountNum account.account_num%type,
 customerRef customer.customer_ref%type,
 internalCreditScore CUSTOMERATTRIBUTES.Internal_Credit_Score%type);

 var_query1Rec query1Record;

 var_nsfDat date;
 var_writeOffdat date;



 cursor cur_accountNum is
 select ACCOUNT_NUM
  from BILLSUMMARY
 where trunc(ACTUAL_BILL_DTM) = p_actBillDat
   and CANCELLATION_REQUEST_DAT is null;
begin
  open cur_accountNum;
  Loop
    fetch cur_accountNum bulk collect
  into var_accountNum limit 100;
close cur_accountNum;
for i in 1 .. var_accountNum.count
loop 
  select A.ACCOUNT_NUM, A.CUSTOMER_REF, CA.INTERNAL_CREDIT_SCORE 
    into var_query1Rec
    from ACCOUNT A, CUSTOMERATTRIBUTES CA, CONTACTDETAILS CD, CONTACT CNT  
            where A.ACCOUNT_NUM = var_accountNum(i) and  
            A.CUSTOMER_REF = CA.CUSTOMER_REF(+) and  
            A.CUSTOMER_REF = CD.CUSTOMER_REF and  
            CNT.CUSTOMER_REF = A.CUSTOMER_REF and  
            CD.CONTACT_SEQ = CNT.CONTACT_SEQ and  
            CD.CONTACT_SEQ = 1 and  
            CD.START_DAT = (select min(CNTD.START_DAT)  
                            from CONTACTDETAILS CNTD  
                            where CNTD.CONTACT_SEQ = CD.CONTACT_SEQ and  
                            CNTD.CUSTOMER_REF = A.CUSTOMER_REF);

  select max(AP.ACCOUNT_PAYMENT_DAT) into var_writeOffdat 
            from ACCOUNT A, ACCOUNTPAYMENT AP  
            where A.ACCOUNT_NUM = AP.ACCOUNT_NUM and  
            A.ACCOUNT_NUM = var_accountNum(i) AND  
            A.TOTAL_WRITEOFF_TOT <> 0 and  
            (AP.PAYMENT_ORIGIN_ID = 2 or  AP.PAYMENT_ORIGIN_ID = 3) and  
            AP.CANCELLED_DTM is null and  
            AP.FAILED_DTM is null;

  select max(PP.FAILED_DTM) into var_nsfDat

                              from ACCOUNTPAYMENT AP, PHYSICALPAYMENT PP  
                              where AP.ACCOUNT_NUM = var_accountNum(i) and   
                              AP.ACCOUNT_PAYMENT_STATUS = 3 and  
                              AP.PHYSICAL_PAYMENT_SEQ = PP.PHYSICAL_PAYMENT_SEQ and  
                              AP.CUSTOMER_REF = PP.CUSTOMER_REF and  
                              PP.PHYSICAL_PAYMENT_STATUS = 3 and  
                              PP.FAILURE_CODE_ID in (select PFC.FAILURE_CODE  
                                                     from CGPAYMENTFAILURECONFIG PFC  
                                                     where PFC.FAILURE_TYPE = 'Decline NSF')  ;

 <how to appned var_query1Rec with  var_writeOffdat and var_writeOffdat>                                 
 <how to make a PLSQl table of that record and return from function>



  end loop;
end loop;

end;

【问题讨论】:

  • 你不能这样做,因为这个变量有不同的类型——其中一个是记录,另外两个是日期。您可以将它们添加到一个集合中,但前提是它们都具有相同的数据类型。作为一个选项 - 您可以添加一些 OUT 参数,然后将它们从函数返回值
  • @Tatiana 函数应该只返回一个值。如果他们想在 SQL 语句中使用它,那么返回对象的函数是最好的方法
  • @kevinsky 据我所知,从 SQL 语句调用的用户定义函数必须返回有效的 SQL 数据类型,而不是特定于 PL/SQL 的类型。所以返回一个对象无论如何都会阻止在 SQL 中使用这个函数

标签: oracle collections plsql


【解决方案1】:

如果这个函数不是包的一部分 - 为什么不呢?那么你别无选择,只能像这个例子一样声明一个 SQL 对象类型:

CREATE TYPE person_typ AS OBJECT (
  idno           NUMBER,
 first_name     VARCHAR2(20)
);

在函数顶部声明变量以访问创建的类型。

type t_arr is table of person_typ ;
l_arr  t_arr := t_arr();

然后在您的代码中分配它们:

l_arr.extend;
l_arr(i).idno := xxx;
l_arr(i).first_name := yyyy;

create函数返回对象:

create or replace function test(p_actBillDat date) return person_typ as
.....
    return(l_arr);
end;

但我会在一个包中拥有这个功能,然后在包体标题或规范中你可以这样做:

type t_rec is
 record(x number
       ,y varchar2(100)
       );
 type t_tbl is table of t_rec index by binary_integer;

然后在你的函数中声明:

 l_tbl t_tbl;

然后在函数中赋值:

l_tbl(i).x := xxx;
l_tbl(i).y := yyy;

最后只需像这样返回函数中的类型:

create or replace function test(p_actBillDat date) return t_tbl as
......
   l_tbl t_tbl;
begin
    .......
     for i in 1..counter loop
         .. SQL statements
         l_tbl(i).x := xxx;
         l_tbl(i).y := yyy;
     end loop;
     return l_tbl;
end;

【讨论】:

  • 可以不接触架构就完成吗?我不想定义 SQL 类型。
  • 是的,正如我所解释的那样,它可以很容易地完成。将函数放入包中 - 查看如何创建包和包体,然后在包体中定义类型,如我在第二个示例中所示。
猜你喜欢
  • 2017-07-26
  • 1970-01-01
  • 2018-01-17
  • 2010-10-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-10-14
  • 1970-01-01
相关资源
最近更新 更多