2015-10-14 114 views
0

我有一个调用返回SYS_REFCURSOR的函数的存储过程。该函数返回一个SYS_REFCURSOR,因为该函数也是从Java应用程序调用的,Java不理解rowtype。将SYS_REFCURSOR强制转换为PL/SQL类型

这是我的功能。

function f_get_building(
    p_building_id in T_BUILDING.ID%type 
) return sys_refcursor 
    AS 
    v_cursor sys_refcursor; 
    BEGIN 

    open v_cursor for 
     select 
      BUILDING_ID, 
      CAMPUS_ID, 
      DELETE_FLAG, 
      max(EFFECTIVE_DATE), 
      END_DATE, 
      IMAGE_URL, 
      INSTITUTION_ID, 
      LOCAL_ID, 
      LOCATION_ID, 
      NAME 
     from V_BUILDING 
     where BUILDING_ID = p_building_id 
     group by 
      BUILDING_ID, 
      CAMPUS_ID, 
      DELETE_FLAG, 
      END_DATE, 
      IMAGE_URL, 
      INSTITUTION_ID, 
      LOCAL_ID, 
      LOCATION_ID, 
      NAME; 

    return v_cursor; 

    END f_get_building; 

在另一个存储过程中我也调用此功能,但使用它有问题。这是存储过程。

procedure sp_delete_building(
    p_building_id in T_BUILDING.ID%type, 
    p_permanent_delete in boolean default false 
) 
    AS 
    v_building_cur sys_refcursor; 
    v_building_rec V_BUILDING%rowtype; 
    BEGIN 

    -- if permanment delete 
    if p_permanent_delete = true 
    then 
     delete from T_BUILDING where ID = p_building_id; 
    -- otherwise perform soft delete 
    else 
     -- lookup 
     v_building_cur := f_get_building(p_building_id); 

     -- if cursor is empty there is nothing to do 
     if v_building_cur%notfound then 
      return; 
     end if; 

     fetch v_building_cur into v_building_rec; -- this line is where the error happens 

     -- if its already deleted nothing to do 
     if v_building_rec.DELETE_FLAG = 'Y' 
     then 
      return; 
     else 
      insert into T_BUILDING_ATTRIBUTE(BUILDING_ID,EFFECTIVE_DATE,DELETE_FLAG, 
       IMAGE_URL,LOCATION_ID,NAME) 
      values (v_building_rec.BUILDING_ID,current_timestamp,'Y',v_building_rec.IMAGE_URL 
       ,v_building_rec.LOCATION_ID,v_building_rec."NAME"); 
     end if; 
    end if; 

    END sp_delete_building; 

我得到以下PL/SQL堆栈跟踪。

ORA-01722: invalid number 
ORA-06512: at "OBR.PKG_BUILDING", line 114 
ORA-06512: at line 8 

原谅我的无知,这是使用PL/SQL我的第一个项目,我将自己归类为一个Java开发者,而不是一个数据库开发人员。因为我从V_BUILDING中选择了所有的东西,所以我希望我能够将它作为存储过程中的rowtype来处理。我如何在存储过程中使用我的函数?

更新:

这里是V_BUILDING

CREATE OR REPLACE FORCE VIEW "OBR"."V_BUILDING" ("BUILDING_ID", "LOCAL_ID", "INSTITUTION_ID", "EFFECTIVE_DATE", "END_DATE", "DELETE_FLAG", "CAMPUS_ID", "LOCATION_ID", "IMAGE_URL", "NAME") AS 
    SELECT 
    ba.BUILDING_ID, 
    b.LOCAL_ID, 
    b.INSTITUTION_ID, 
    ba.EFFECTIVE_DATE, 
    NVL(MIN(ba2.EFFECTIVE_DATE - INTERVAL '0.000001' SECOND),TO_DATE('31-DEC-9999', 'DD-MON-YYYY')) AS END_DATE, 
    ba.DELETE_FLAG, 
    ba.CAMPUS_ID, 
    ba.LOCATION_ID, 
    ba.IMAGE_URL, 
    ba.NAME 
FROM 
    T_BUILDING b 
INNER JOIN T_BUILDING_ATTRIBUTE ba 
    ON b.ID = ba.BUILDING_ID 
LEFT JOIN T_BUILDING_ATTRIBUTE ba2 
    ON ba.BUILDING_ID = ba2.BUILDING_ID 
    AND ba2.EFFECTIVE_DATE > ba.EFFECTIVE_DATE 
GROUP BY 
    ba.BUILDING_ID, 
    b.LOCAL_ID, 
    b.INSTITUTION_ID, 
    ba.EFFECTIVE_DATE, 
    ba.DELETE_FLAG, 
    ba.CAMPUS_ID, 
    ba.LOCATION_ID, 
    ba.IMAGE_URL, 
    ba.NAME 
ORDER BY ba.BUILDING_ID, ba.EFFECTIVE_DATE DESC; 

更新2创建语句:

这里是类型的视图

enter image description here

截图CAMPUS_ID - NUMBER(10) LOCATION_ID - NUMBER(10) IMAGE_URL - VARCHAR(500) NAME - VARCHAR(255) BUILDING_ID - NUMBER(10) LOCAL_ID - VARCHAR(30) INSTITUTION_ID - NUMBER(10) EFFECTIVE_DATE - TIMESTAMP(6) END_DATE - TIMESTAMP(6) DELETE_FLAG - CHAR(1)

+1

引用游标是否以与它们在表中显示的顺序相同的顺序返回所有v_building列? – Boneist

+0

如果您可以编辑问题以包含v_building表的create table语句,那将会很有帮助。 – Boneist

+0

我已经为视图添加了创建ddl – greyfox

回答

1

这里是列及其数据类型的列表中的观点和ref光标为退货:

LIST OF COLS FROM VIEW DATATYPE FROM VIEW LIST OF COLS FROM CURSOR DATATYPE FROM CURSOR 
---------------------- ------------------ ------------------------ -------------------- 
BUILDING_ID    NUMBER(10)   BUILDING_ID    NUMBER(10) 
LOCAL_ID    VARCHAR(30)   CAMPUS_ID     NUMBER(10) 
INSTITUTION_ID   NUMBER(10)   DELETE_FLAG    CHAR(1) 
EFFECTIVE_DATE   TIMESTAMP(6)  max(EFFECTIVE_DATE)  TIMESTAMP(6) 
END_DATE    TIMESTAMP(6)  END_DATE     TIMESTAMP(6) 
DELETE_FLAG    CHAR(1)    IMAGE_URL     VARCHAR(500) 
CAMPUS_ID    NUMBER(10)   INSTITUTION_ID   NUMBER(10) 
LOCATION_ID    NUMBER(10)   LOCAL_ID     VARCHAR(30) 
IMAGE_URL    VARCHAR(500)  LOCATION_ID    NUMBER(10) 
NAME     VARCHAR(255)  NAME      VARCHAR(255) 

他们是不一样的,但通过在您的使用V_BUILDING%ROWTYPE sp_delete_building过程中,您将引用游标结果视为列顺序与视图的顺序相同。

您可以看到视图的数据类型与光标选择列表之间有几个不匹配 - 可能是导致您看到无效数字错误的“LOCATION_ID/LOCAL_ID”不匹配。

您可能需要更改引用游标的顺序,以便按照与视图相同的顺序返回列的列表,或者在v_building_rec记录类型中明确列出游标的列。

另外,你应该给你的max(EFFECTIVE_DATE)列的refcursor一个别名。

+0

你是对的,一旦我改变了我的选择顺序,它按预期工作。非常感谢! – greyfox

+0

没问题* {:-)出于好奇,你为什么要使用ref cursor?它看起来并不像你在PL/SQL之外传递这个游标 - 你能不能把它声明为一个“普通”游标,有一个参数,也许在包体层次上? (例如'cursor building_cur is select ...')这样,您可以直接使用基于游标rowtype的类型,并且您不必担心列顺序太多。 – Boneist

+0

该函数也是从Java Web应用程序调用使用MyBatis调用该函数并将其映射到java域对象,可能有更好的方法来做到这一点,但它是我能想到的最简单的方法,我可以利用函数从我的Java应用程序和其他PL/SQL代码 – greyfox

相关问题