【问题标题】:Returning data from an array table parameter from an Oracle SP从 Oracle SP 的数组表参数返回数据
【发布时间】:2019-12-23 04:10:11
【问题描述】:

我有这个 C# 代码来调用 Oracle 存储过程:

using (OracleConnection oracleConnection = new OracleConnection(connectionString))
{
    oracleConnection.Open();
    OracleCommand oracleCommand = new OracleCommand();

    oracleCommand.Parameters.Add(new OracleParameter
    {
        ParameterName = "eventids",
        Direction = ParameterDirection.Input,
        CollectionType = OracleCollectionType.PLSQLAssociativeArray,
        Value = new string[] { "Test1", "Test2" },
        Size = 2,
        UdtTypeName = "T_STRING_TAB"
    });
    oracleCommand.Parameters.Add("p_cursor", OracleDbType.RefCursor).Direction = ParameterDirection.Output;

    oracleCommand.Connection = oracleConnection;
    oracleCommand.CommandText = "spTest";
    oracleCommand.CommandType = CommandType.StoredProcedure;

    using (OracleDataReader oracleDataReader = oracleCommand.ExecuteReader())
    {
        while (oracleDataReader.Read())
        {
            int fieldCount = oracleDataReader.FieldCount;
            string s = oracleDataReader.GetString(0);
        }
    }               
}

我在数据库中有这个:

create or replace noneditionable package pp is
  type t_string_tab is table of varchar2(260) index by binary_integer;
end;

create or replace noneditionable procedure sptest(
  eventids in pp.t_string_tab,
  p_cursor in out sys_refcursor)
as
begin
  open p_cursor for 
    select p.column_value, 'Test1', 'Test2' from table(eventids) p;
end;

当我从代码中调用此过程时,出现以下错误:

Oracle.ManagedDataAccess.Client.OracleException:
ORA-21700: 对象不存在或被标记为删除
ORA-06512:在“PPUSER.SPGETMETADATA”,第 6 行 ORA-06512:在第 1 行'

这似乎与无法从存储过程访问的 T_STRING_TAB 类型有关?

即使我将存储过程放在 PP 包中并在代码中调用 PP.spTest,也会出现此错误。我还尝试在代码中使用 PP.T_STRING_TAB 作为 UdtTypeName,但这不起作用。我无法将类型设为全局,否则会出现以下错误:

PLS-00355:在此上下文中不允许使用 PL/SQL 表

请注意,我添加了一个新用户,这可能与权限有关吗?

我不确定自己做错了什么 - 我不是 Oracle 专家!

这个问题来自How to pass an array of strings from C# to an Oracle stored procedure

【问题讨论】:

  • 在这个网站 (dbtricks.com/?p=216 ) 中,它建议授予用户执行该类型的权限。你试过吗?
  • 这是一个在包中定义的 PL/SQL 关联数组,因此需要在包上执行。
  • 没有类型t_string_tab。只有pp.t_string_type。我不懂 C#,所以无法判断赋值是否正确,但对 PL/SQL 类型和 SQL 类型之间的这种类型转换的支持高度依赖于版本。您的 Oracle 版本是多少?
  • 我试图授予对包的执行权限(应该做类型),但没有奏效。我试图将 sp 添加到包中,但这也不起作用。 Oracle 版本是 OraDB18Home1。
  • 如果您从实际提供的值中选择数据作为输入,那将毫无意义。如果您只想将string[] 转换为DataReaderDataTable,则无需为此调用Oracle。

标签: c# oracle plsql


【解决方案1】:

您可以尝试在架构级别创建类型。

CREATE type t_string_tab is table of varchar2(260);

现在您可以在 select 语句中使用它,如下所示:

select p.column_value, 'Test1', 'Test2' from table(eventids) p;

干杯!!

【讨论】:

  • 正如我所提到的,我无法创建“全局”类型。我收到错误:1/22 PLS-00355:在此上下文中不允许使用 pl/sql 表
  • 您不能在架构级别创建关联数组(或索引表)。它只能在 PL/SQL 块或包中定义。您只能在架构级别创建 VARRAY 或嵌套表,请参阅Collection Types
  • 你测试了吗?我怀疑你是否可以运行 table(cast eventids as t_string_tab) - 反正语法是错误的。
  • 是的,我之前的回答是正确的,只是错误地在这个版本中错误地更新了它。哈哈。现在更新了答案
  • 但是你不能在.NET中绑定嵌套表参数,它只支持PLSQLAssociativeArray
【解决方案2】:

您必须将关联数组(索引表)转换为嵌套表。可能是这样的:

CREATE type string_table_type is table of varchar2(260);


create or replace package pp is
  type t_string_tab is table of varchar2(260) index by binary_integer;
  function sptest(eventids in t_string_tab) RETURN p_cursor sys_refcursor;
end;

create or replace package body pp is

function sptest(eventids in t_string_tab) RETURN sys_refcursor as    
   p_cursor sys_refcursor;
   string_tab := string_table_type();
begin
   for i in eventids.FIRST..eventids.LAST LOOP
       string_tab.EXTEND();
       string_tab(string_tab.LAST) := eventids(i);
   end loop;
  open p_cursor for 
    select p.column_value, 'Test1', 'Test2' from table(string_tab) p;
  RETURN p_cursor;
end sptest;

end;

如果您有一个返回值,那么我更喜欢 FUNCTION 而不是带有一个 OUT 参数的 PROCEDURE,但这更多的是个人喜好问题。

【讨论】:

    猜你喜欢
    • 2011-01-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-02
    • 2014-11-03
    • 2011-03-02
    • 1970-01-01
    • 2017-09-02
    相关资源
    最近更新 更多