2015-10-14 37 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

相關問題