如何从Oracle中的函数返回记录集

时间:2018-08-03 06:03:42

标签: oracle plsql oracle11g user-defined-types

我试图通过传递值来使用函数获取记录数据

请找到以下内容

CREATE TABLE "TEST" 
   (    "TEST_ID" NUMBER(9,0) NOT NULL ENABLE, 
    "TEST_DESC" VARCHAR2(30 BYTE), 
    "TEST_DATE" DATE
); 

create or replace TYPE TEST_OBJ_TYPE IS OBJECT
(
TEST_ID   NUMBER(9),
TEST_DESC VARCHAR(30),
dates date
);

create or replace TYPE TEST_TABTYPE AS TABLE OF TEST_OBJ_TYPE;

使用上述对象和表类型创建函数如下

create or replace FUNCTION GET_ROWS(dates date)RETURN TEST_TABTYPE
AS
V_Test_Tabtype Test_TabType;
table_name varchar2(30);
q1 varchar2(300);
BEGIN

            table_name :='Test';

                q1 := 'SELECT TEST_OBJ_TYPE(A.TEST_ID, A.TEST_DESC)FROM' || '
                      (SELECT TEST_ID, TEST_DESC FROM ' || table_name || ' where 
                       TEST_DATE = '''||dates||''' ) A';
            dbms_output.put_line(q1); 
            EXECUTE IMMEDIATE  q1  BULK COLLECT INTO V_Test_TabType ;

            RETURN V_Test_TabType;

           EXCEPTION
           WHEN OTHERS THEN
           v_Test_TabType.DELETE;
           RETURN v_Test_TabType;
END;

执行此操作时,SQL可以正确打印,但未提供记录值。

Error as follows:
select (GET_ROWS('01-08-18')) from dual
Error report -
ORA-02315: incorrect number of arguments for default constructor
ORA-06512: at "AMTEL_MIS.GET_ROWS", line 13

SELECT TEST_OBJ_TYPE(A.TEST_ID, A.TEST_DESC) FROM (SELECT TEST_ID, TEST_DESC FROM Test where TEST_DATE = '01-08-18' ) A

请进一步帮助我

预先感谢

1 个答案:

答案 0 :(得分:2)

您的类型TEST_OBJ_TYPE是用三个属性定义的:TEST_IDTEST_DESCDATES。但是,您的查询仅用两列填充了构造函数:

SELECT TEST_OBJ_TYPE(A.TEST_ID, A.TEST_DESC) FROM

您缺少DATES的值,这就是Oracle催促ORA-02315的原因。

  

我已经按照您的建议进行了尝试,但这给了我一个错误
  ORA-00904: "A"."DATES": invalid identifier

由于函数的编写方式复杂,因此需要在子查询和对象构造函数中都包含TEST_DATE(或dates):

 q1 := 'SELECT TEST_OBJ_TYPE(A.TEST_ID, A.TEST_DESC,A.TEST_DATE)FROM' || '  -- here!
             (SELECT TEST_ID, TEST_DESC, TEST_DATE FROM '  -- and here!
              || table_name || ' where TEST_DATE = '''||dates||''' ) A'; 

如果这样做,您的代码将起作用。这里是a LiveSQL demo of your code的修复程序。 (需要免费的Oracle登录名。)

您似乎希望输入表名,因此这是执行此操作的代码版本:

create or replace function get_rows(dates date, p_table_name in varchar2) 
    return test_tabtype   
as   
    v_test_tabtype test_tabtype;   
    q1 varchar2(300);   
begin   

    q1 := 'select test_obj_type(a.test_id, a.test_desc,a.test_date) from' 
             || '(select test_id, test_desc, test_date from ' 
             || p_table_name 
             || ' where test_date = :1 ) a';   
    dbms_output.put_line(q1);    

    execute immediate  q1  
        bulk collect into v_test_tabtype
        using dates ;   

    return v_test_tabtype;   

exception   
     when others then   
        v_test_tabtype.delete;   
        return v_test_tabtype;   
end;

请注意,在使用一致的大小写和常规缩进进行布局时,理解代码要容易得多。可读性是一个功能!