在 C# 中通过 varchar2 使用 PL/SQL assoc 数组索引

Posted

技术标签:

【中文标题】在 C# 中通过 varchar2 使用 PL/SQL assoc 数组索引【英文标题】:using PL/SQL assoc array index by varchar2 in C# 【发布时间】:2014-10-10 07:51:24 【问题描述】:

我有 PL/SQL 代码:

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; 

控制代码检查 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:语句被忽略”

这是一个特殊情况,当我使用由 varchar2 索引的 assoc 数组时。 当我在整数包中更改返回类型的索引时(注释掉行代码 id 包),一切正常。

你知道如何在 C# 中使用这个包吗?

谢谢

【问题讨论】:

上次我检查 ODP.NET (10.2) 时,它无法处理 varchar2-indexed 集合。我不知何故怀疑它会随着时间而改变。 (顺便说一句。我喜欢那个“riadok”和“stĺpec”。:-)) 【参考方案1】:

尽管ODP.NET Developer's Guide 和Oracle Call Interface Programmer's Guide 都没有明确提及它并且似乎没有人确切知道,但您似乎无法绑定varchar2-indexed 关联数组。我从 C#(通过 ODP.NET 10.2)和 php 5.something(通过 OCI)尝试了它,但没有成功。

【讨论】:

我和同事讨论过这个话题我们也得出了同样的结论。在所有手动工作中,仅使用整数索引。这个问题可以通过使用数据类型对象来绕过。也许。我会试试的 对于我一直在设计的 .NET->DB 接口 API(以及我刚刚走过的其他一些项目),他们使用将结构化数据分解为几个相同的标量类型关联数组长度,然后在 DB 端将它们重新组合为记录集合或 varchar2 索引数组。那是当时的 ODP.NET 10。我想我已经看到了一些关于在 ODP.NET 11+ 中将结构/记录的(pls_integer-indexed 或 varray)集合从 .NET 直接传递到 DB 的信息,但是,唉,从在这里你是你自己的,我没有 ODP.NET 11+ 的经验来帮助你。 :-(【参考方案2】:

所以我尝试使用数据类型对象。

第一步,我创建 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来说是没有问题的。

【讨论】:

以上是关于在 C# 中通过 varchar2 使用 PL/SQL assoc 数组索引的主要内容,如果未能解决你的问题,请参考以下文章

在 Store C# 中通过哈希查找证书

如何在 C# 中通过指纹查找证书

在 Visual Studio 中通过 C# (Selenium) 自动登录 Gmail

在 Visual Studio C# 中通过代码打开 Word 文档

在 Visual Studio 中通过 C# 类编译 C++ 代码

C#:在 WPF 中通过按钮访问下一个或上一个元素