将SYS_REFCURSOR转换为PL / SQL类型

时间:2015-10-14 15:04:31

标签: oracle stored-procedures plsql

我有一个存储过程调用一个返回SYS_REFCURSOR的函数。该函数返回一个SYS_REFCURSOR,因为此函数也是从Java应用程序调用的,Java不理解rowtype。

这是我的功能。

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) 名称 - VARCHAR(255) BUILDING_ID - 数量(10) LOCAL_ID - VARCHAR(30) INSTITUTION_ID - NUMBER(10) EFFECTIVE_DATE - TIMESTAMP(6) END_DATE - TIMESTAMP(6) DELETE_FLAG - CHAR(1)

1 个答案:

答案 0 :(得分:1)

以下是视图和引用游标返回的列及其数据类型列表:

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)

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

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

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

顺便说一句,您应该在refcursor中为max(EFFECTIVE_DATE)列添加别名。