![](/img/trans.png)
[英]java.sql.SQLException: Invalid column type when executing procedure with package level types from jdbc
[英]Oracle JDBC / PL SQL / TYPE / Package Level / Invalid Name Pattern
我已經以這種方式聲明了包級別類型(使用Oracle XE 11):
create or replace PACKAGE RM_TYPES
AS
TYPE RECPPART_ARR IS TABLE OF RM_RECEPCIONPARTIDAS%ROWTYPE;
END RM_TYPES;
我有這樣的SP:
create or replace PROCEDURE "RM_TRY_B" (partidas OUT RM_TYPES.RECPPART_ARR) as
begin
SELECT * BULK COLLECT INTO partidas FROM rm_recepcionpartidas;
end;
我有這樣的Java代碼:
CallableStatement cstmt = conn.prepareCall("{call RM_TRY_B(?)}");
cstmt.registerOutParameter(1, OracleTypes.ARRAY, "RM_TYPES.RECPPART_ARR");
cstmt.execute();
Array a = cstmt.getArray(1);
它給我一個驚喜:
Exception in thread "main" java.sql.SQLException: invalid name pattern: RM_TYPES.RECPPART_ARR
通過向oracle發出以下命令,我已經向用戶授予了對軟件包的訪問權限:
GRANT EXECUTE ON RM_TYPES TO myuser;
我以此為參考: https : //docs.oracle.com/database/121/JJDBC/apxref.htm#JJDBC28913 (本節名為:使用%ROWTYPE屬性為每一行創建Java級別對象
我在哪里做錯了?
我也嘗試在我的Java代碼中傳遞此名稱:“ RECPPART_ARR”或“ MYSCHEMA.RM_TYPES.RECPPART_ARR”,它們都不起作用。
然后我讀到有人在stackoverflow上這樣說: java-在oracle存儲過程中傳遞數組 :“實際上問題是java中不可見在包中創建的任何類型。如果我在模式級別創建該類型,則它可以工作。”
是真的嗎
然后,也許我應該在架構級別定義別名?
怎么樣? 我嘗試了“ CREATE SYNONYM”:
CREATE PUBLIC SYNONYM RECPPART_ARRAY FOR RM_TYPES.RECPPART_ARR;
然后(試圖修改我的SP):
create or replace PROCEDURE "RM_TRY_B" (partidas OUT RECPPART_ARRAY) as
begin
SELECT * BULK COLLECT INTO partidas FROM rm_recepcionpartidas;
end;
但是這次,此SP無法編譯,並在SQLDeveloper中顯示以下錯誤消息:Error(1,36):PLS-00905:對象MYSCHEMA.RECPPART_ARRAY無效。
然后,我嘗試使用sp的先前定義:
create or replace PROCEDURE "RM_TRY_B" (partidas OUT RM_TYPES.RECPPART_ARR) as
begin
SELECT * BULK COLLECT INTO partidas FROM rm_recepcionpartidas;
end;
並修改了我的Java代碼以使用同義詞:
CallableStatement cstmt = conn.prepareCall("{call RM_TRY_B(?)}");
cstmt.registerOutParameter(1, OracleTypes.ARRAY, "RECPPART_ARRAY");
cstmt.execute();
Array a = cstmt.getArray(1);
仍然,異常,並顯示以下消息:無法構造描述符:無法解析類型:“ MYSCHEMA.RECPPART_ARRAY”
加成
我剛發現的一些其他信息:
有人寫道:我有同樣的問題。 通過創建公共同義詞並提供贈款來解決該問題。
如您所見,我已經做到了,但是對我來說沒有運氣。
加成
或...也許在oracle中是這樣的(閱讀本文: http : //docs.oracle.com/javadb/10.10.1.2/ref/rrefsqljgrant.html ):
create or replace PACKAGE RM_TYPES
AS
TYPE RECPPART_ARR IS TABLE OF RM_RECEPCIONPARTIDAS%ROWTYPE;
END RM_TYPES;
sqlplus (logged in as sys as SYSDBA)> GRANT USAGE ON TYPE RM_TYPES.RECPPART_ARR TO myuser;
CREATE PUBLIC SYNONYM RECPPART_ARRAY FOR RM_TYPES.RECPPART_ARR;
create or replace PROCEDURE "RM_TRY_B" (partidas OUT RM_TYPES.RECPPART_ARR) as
begin
SELECT * BULK COLLECT INTO partidas FROM rm_recepcionpartidas;
end;
....
我嘗試過...,甚至使用用戶“ sys”作為SYSDBA身份登錄....發出授權時出現錯誤:
錯誤從第1行開始-命令-向myuser授予RM_TYPES.RECP_ARR上的許可使用類型錯誤報告-SQL錯誤:ORA-00990:特權00990缺失或無效。00000-“特權缺失或無效” *原因:
*行動:
我現在快要瘋了。
JDBC對PL / SQL數據類型作為參數的支持是Oracle 12c的一項新功能。
PL / SQL類型的外觀和行為類似於常規類型; 它們可以在SQL和其他上下文中使用,它們具有TYPE_OID和TYPECODE,並且具有數據字典視圖(DBA_PLSQL_TYPES)。 一個奇怪的區別是PL / SQL類型未顯示在DBA_OBJECTS中。
在舊版本中,必須創建TYPE作為獨立對象,才能在PL / SQL之外使用它。 這樣的代碼可以創建對象:
CREATE OR REPLACE TYPE RECPPART_REC IS OBJECT
(
--list RM_RECEPCIONPARTIDAS columns here. %ROWTYPE is not available in SQL.
);
CREATE OR REPLACE RECPPART_ARR IS TABLE OF RECPPART_REC;
您可以利用PL / SQL中鮮為人知的功能: PIPELINED
函數。 一個例子:
create table tab (
id number(7)
);
/
insert into tab values (1);
insert into tab values (2);
create or replace package pkg
as
type typ is table of tab%rowtype;
end pkg;
/
create or replace procedure proc (param out pkg.typ) as
begin
select * bulk collect into param from tab;
end;
/
create or replace function func return pkg.typ pipelined as
begin
for rec in (select * from tab) loop
pipe row(rec);
end loop;
end;
/
select * from table(func);
以上將產生:
ID
--
1
2
因此,您也可以從JDBC輕松實現表類型。
這樣做的原因是每個流水線函數都會隱式創建一個與您的PL / SQL表類型相同的頂級SQL類型。 在上述情況下,例如:
create or replace type SYS_PLSQL_29848_13_1 as object (ID NUMBER(7));
create or replace type SYS_PLSQL_29753_9_1 as table of SYS_PLSQL_29848_13_1;
這更多是一個旁注。 通常,您可能應該選擇喬恩·海勒(Jon Heller)建議的方法
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.