2014-10-10 22 views
0

我有PL/SQL代碼:在C#中使用PL/SQL ASSOC數組索引由VARCHAR2

create or replace 
package  TEST_PKG2 as 
    type AssocArray is table of varchar2(20) index by binary_integer; 
    type AssocArray_varchar is table of varchar2(20) index by varchar2(10); 
    --type AssocArray_varchar is table of varchar2(20) index by integer; 

    function assoc_arry_return(Param1 in AssocArray) return AssocArray_varchar; 
end TEST_PKG2; 

create or replace 
package body  TEST_PKG2 as 
    function assoc_arry_return(Param1 in AssocArray) return AssocArray_varchar 
    is 
    v_return_value AssocArray_varchar;  
    begin 
    v_return_value('name1'):=Param1(1); 
    v_return_value('name2'):=Param1(2); 
    v_return_value('name3'):=Param1(3); 

    return v_return_value; 
    end assoc_arry_return; 
end TEST_PKG2; 

CONTROLE代碼來檢查PL/SQL:

set serveroutput on 
declare 
    assoc_array test_pkg2.AssocArray; 
    assoc_array_return test_pkg2.AssocArray_varchar; 

begin 
    assoc_array(1):='test1'; 
    assoc_array(2):='test2'; 
    assoc_array(3):='test3'; 
    assoc_array_return:= test_pkg2.assoc_arry_return(assoc_array); 
    dbms_output.put_line(assoc_array_return.first||' - '||assoc_array_return(assoc_array_return.first)); 
end; 

和C爲執行該功能#代碼:

command = new OracleCommand("TEST_PKG2.assoc_arry_return", OracleConnection); 
       command.CommandType = CommandType.StoredProcedure; 
       OracleParameter return_value = new OracleParameter(); 
       return_value.OracleDbType = OracleDbType.Varchar2; 
       return_value.Direction = ParameterDirection.ReturnValue; 
       return_value.CollectionType = OracleCollectionType.PLSQLAssociativeArray; 
       return_value.Size=3; 
       return_value.ArrayBindSize = new int[3] { 20, 20, 20 }; 
       command.Parameters.Add(return_value); 

       OracleParameter Param4 = command.Parameters.Add("Param1", OracleDbType.Varchar2); 
       Param4.Direction = ParameterDirection.Input; 
       Param4.CollectionType = OracleCollectionType.PLSQLAssociativeArray; 
       Param4.Value = new string[3] { "First Element", "Second Element", "Third Element" }; 
       Param4.Size = 3; 
       Param4.ArrayBindSize = new int[3] { 20, 20, 20 }; 
       Param4.ArrayBindStatus = new OracleParameterStatus[3] { OracleParameterStatus.Success, OracleParameterStatus.Success, OracleParameterStatus.Success }; 
       command.ExecuteNonQuery(); 

當我與THIC代碼執行的應用程序,執行對最後一行與模具錯誤「ORA-06550:第1行,第15欄: PLS-00382:表達式是錯誤的類型 ORA-06550的:第1行,第7列: PL/SQL:語句忽略」

這是一種特殊情況,當我使用ASSOC陣列由VARCHAR2索引。 當我更改索引由返回類型包在整數(註釋掉行代碼id包),一切正常。

你知道如何在C#中使用這個包嗎?

感謝的

+1

上次我檢查了ODP.NET(10.2),它無法處理'varchar2'索引的集合。我懷疑它隨着時間而改變。 (順便說一下,我喜歡那個「riadok」和「stĺpec」。:-)) – nop77svk 2014-10-10 07:57:22

回答

0

雖然也不ODP.NET Developer's Guide,也不Oracle Call Interface Programmer's Guide也明確提到它,似乎沒有人確切地知道,看來你就是不能綁定varchar2 -indexed關聯數組。我嘗試了C#(通過ODP.NET 10.2)和PHP 5.something(通過OCI),但沒有成功。

+0

我和我的同事們討論過這個話題,我們也得出了同樣的結論。在所有手動工作中只使用索引整數。 可以通過使用數據類型對象繞過此問題。也許。 我會試試 – tomySK 2014-10-11 17:56:22

+0

對於我一直在設計的.NET-> DB接口API(以及其他一些我剛剛走過的項目),他們將結構化數據分解爲幾個相同長度的標量類型關聯數組,然後再將它們在數據庫一側重新組合到記錄或varchar2索引數組的集合中。那是當時ODP.NET 10.我想我已經看過一些關於從.NET到DB直接在ODP.NET 11+中傳遞(pls_integer-indexed或varray)結構/記錄的集合的信息,但是,在這裏你是獨立的,我沒有ODP.NET 11+的經驗,以幫助你。 :-( – nop77svk 2014-10-11 18:52:44

0

所以我嘗試使用數據類型的對象。

在第一步驟中創建對象DATA_TYPE

create or replace type STB_JIG_TARLOG_VALUE as object 
(
    NAME varchar2(300), 
    VALUE varchar2(500) 
) 

create or replace type 
    STB_JIG_TARLOG_VALUES is table of STB_JIG_TARLOG_VALUE 

它們不是包的一部分。

我現在也可以使用這種類型的返回類型的函數:

function get_data(...) return STB_JIG_TARLOG_VALUES 
    is 
    items STB_JIG_TARLOG_VALUES := STB_JIG_TARLOG_VALUES(); 
    begin 
    items.extend; 
    items(1):= STB_JIG_TARLOG_VALUE('key_name','key_value'); 
    ... 
end get_data; 

,最後我們得到的返回值只是選擇:

select * from table (get_data(...)); 

名稱在STB_JIG_TARLOG_VALUE定義並且爲返回值添加值可以採用不同的方式(例如循環...)

並且從此查詢中獲取數據與DataReader沒有問題。