C# 通过c将整数数组传递给oracle过程#

C# 通过c将整数数组传递给oracle过程#,c#,arrays,oracle,stored-procedures,C#,Arrays,Oracle,Stored Procedures,我想通过c#将整数数组传递给存储过程。该过程通过sql developer工作,但在c#中不起作用。这是我的密码,但我被密码卡住了 调用“V1”时参数的数目或类型错误。错误。请帮帮我 c#代码: 和我的类型: create or replace TYPE INNUMARRAY AS TABLE OF INTEGER; 关联数组由create或replace TYPE INNUMARRAY定义为PLS\u INTEGER的整数索引表 但是,不能在表(…)表达式中使用关联数组。为此,必须将关联数组

我想通过c#将整数数组传递给存储过程。该过程通过sql developer工作,但在c#中不起作用。这是我的密码,但我被密码卡住了
调用“V1”时参数的数目或类型错误。
错误。请帮帮我 c#代码:

和我的类型:

create or replace TYPE INNUMARRAY AS TABLE OF INTEGER;

关联数组由
create或replace TYPE INNUMARRAY定义为PLS\u INTEGER的整数索引表

但是,不能在
表(…)
表达式中使用关联数组。为此,必须将关联数组转换为嵌套表(不使用PLS_INTEGER索引),例如:

create or replace TYPE VehicleGroupID_TableType AS TABLE OF INTEGER;

或更简短的版本:

WHERE  "VehicleGroupDetail"."VehicleGroupID" MEMBER OF VehicleGroupID_Table
您的类型:

create or replace TYPE INNUMARRAY AS TABLE OF INTEGER;
是在SQL作用域中定义的集合

你通过的论点:

p_strings.CollectionType = OracleCollectionType.PLSQLAssociativeArray;
p_strings.Value = new int[5]{1,2,3,4,5};
是一个关联数组,只能在PL/SQL作用域中定义(即在包中或PL/SQL块中),不能在SQL作用域中使用

它们是两种不同且不兼容的数据类型

相反,您可以在包中创建关联数组类型,然后手动将关联数组中的每个值提取到可在SQL作用域中使用的集合中:

CREATE PACKAGE vehicles_pkg IS
  TYPE INNUMASSOCARRAY IS TABLE OF INTEGER INDEX BY BINARY_INTEGER;

  PROCEDURE v1
  (
    VehicleGroupID_Array IN INNUMASSOCARRAY
  );
END;
/

CREATE PACKAGE BODY vehicles_pkg IS
  PROCEDURE v1
  (
    VehicleGroupID_Array IN INNUMASSOCARRAY
  )
  IS
    p_recordset SYS_REFCURSOR;
    p_array     INNUMARRAY := INNUMARRAY();
    i           BINARY_INTEGER;
  BEGIN
    i := VehicleGroupID_Array.FIRST;
    WHILE i IS NOT NULL LOOP
      p_array.EXTEND;
      p_array( p_array.COUNT ) := VehicleGroupID_Array(i);
      i := VehicleGroupID_Array.NEXT(i);
    END LOOP;

    -- Rest of your procedure using p_array instead of the associative array.
  END;
END;
/

我可以在包外部定义关联数组类型吗?我希望它们是独立的

否,但您可以定义仅包含以下类型的包:

CREATE PACKAGE vehicles_pkg IS
  TYPE INNUMASSOCARRAY IS TABLE OF INTEGER INDEX BY BINARY_INTEGER;
END;
/

CREATE PROCEDURE v1
(
  VehicleGroupID_Array IN vehicles_pkg.INNUMASSOCARRAY
)
IS
  p_recordset SYS_REFCURSOR;
  p_array     INNUMARRAY := INNUMARRAY();
  i           BINARY_INTEGER;
BEGIN
  i := VehicleGroupID_Array.FIRST;
  WHILE i IS NOT NULL LOOP
    p_array.EXTEND;
    p_array( p_array.COUNT ) := VehicleGroupID_Array(i);
    i := VehicleGroupID_Array.NEXT(i);
  END LOOP;

  -- Rest of your procedure using p_array instead of the associative array.
END;
/
或者,更好的做法是在包中创建一些通用命名的类型和函数,以将关联数组转换为集合,然后在过程中重用它们:

Oracle 11g R2架构设置

CREATE TYPE IntList AS TABLE OF INTEGER
/

CREATE PACKAGE tools IS
  TYPE IntMap IS TABLE OF INTEGER INDEX BY BINARY_INTEGER;

  FUNCTION IntMapToList(
    i_map IntMap
  ) RETURN IntList;
END;
/

CREATE PACKAGE BODY tools IS
  FUNCTION IntMapToList(
    i_map IntMap
  ) RETURN IntList
  IS
    o_list IntList := IntList();
    i      BINARY_INTEGER;
  BEGIN
    IF i_map IS NOT NULL THEN
      i := o_list.FIRST;
      WHILE i IS NOT NULL LOOP
        o_list.EXTEND;
        o_list( o_list.COUNT ) := i_map( i );
        i := i_map.NEXT( i );
      END LOOP;
    END IF;
    RETURN o_list;
  END;
END;
/

CREATE PROCEDURE v1
(
  VehicleGroupID_Array IN tools.IntMap
)
IS
  p_recordset SYS_REFCURSOR;
  p_array     IntList := tools.IntMapToList( VehicleGroupID_Array );
  i           BINARY_INTEGER;
BEGIN
  -- Rest of your procedure using p_array instead of the associative array.
  NULL;
END;
/

不能在SQL作用域中使用
create或REPLACE TYPE
创建关联数组,因为它只能在PL/SQL作用域中定义。另外,
用于数组中的i.FIRST。。array.LAST循环
在数组稀疏的情况下可能并不总是有效(这不应该在使用OPs方法的C#中发生,但如果从另一个源调用该过程,则可能会发生)。我假设的成员也可以使用本地类型-但我没有测试PL/SQL范围中定义的集合不能在Oracle 11及更早版本的SQL范围中使用(无论是使用
运算符的
成员还是表集合表达式)。它们可以使用Oracle 12中PL/SQL作用域中本地定义的类型(但是关联数组仍然不起作用)。我不想创建关联数组类型。我可以将集合传递给过程吗?@masoudvali是的……但不使用C,因为出于某种原因,C只支持传递关联数组。我可以在包之外定义关联数组类型吗?我希望它们是独立的@MT0@masoudvali毫无用处(您可以在匿名PL/SQL块中定义它,但不能在过程中或从C#引用它)。如果您希望它是独立的,请在包中定义类型,并在SQL范围中定义过程-我将很快添加一个更新。有些人无法信服,尽管它永远不会比这更简洁:-)
CREATE PACKAGE vehicles_pkg IS
  TYPE INNUMASSOCARRAY IS TABLE OF INTEGER INDEX BY BINARY_INTEGER;

  PROCEDURE v1
  (
    VehicleGroupID_Array IN INNUMASSOCARRAY
  );
END;
/

CREATE PACKAGE BODY vehicles_pkg IS
  PROCEDURE v1
  (
    VehicleGroupID_Array IN INNUMASSOCARRAY
  )
  IS
    p_recordset SYS_REFCURSOR;
    p_array     INNUMARRAY := INNUMARRAY();
    i           BINARY_INTEGER;
  BEGIN
    i := VehicleGroupID_Array.FIRST;
    WHILE i IS NOT NULL LOOP
      p_array.EXTEND;
      p_array( p_array.COUNT ) := VehicleGroupID_Array(i);
      i := VehicleGroupID_Array.NEXT(i);
    END LOOP;

    -- Rest of your procedure using p_array instead of the associative array.
  END;
END;
/
CREATE PACKAGE vehicles_pkg IS
  TYPE INNUMASSOCARRAY IS TABLE OF INTEGER INDEX BY BINARY_INTEGER;
END;
/

CREATE PROCEDURE v1
(
  VehicleGroupID_Array IN vehicles_pkg.INNUMASSOCARRAY
)
IS
  p_recordset SYS_REFCURSOR;
  p_array     INNUMARRAY := INNUMARRAY();
  i           BINARY_INTEGER;
BEGIN
  i := VehicleGroupID_Array.FIRST;
  WHILE i IS NOT NULL LOOP
    p_array.EXTEND;
    p_array( p_array.COUNT ) := VehicleGroupID_Array(i);
    i := VehicleGroupID_Array.NEXT(i);
  END LOOP;

  -- Rest of your procedure using p_array instead of the associative array.
END;
/
CREATE TYPE IntList AS TABLE OF INTEGER
/

CREATE PACKAGE tools IS
  TYPE IntMap IS TABLE OF INTEGER INDEX BY BINARY_INTEGER;

  FUNCTION IntMapToList(
    i_map IntMap
  ) RETURN IntList;
END;
/

CREATE PACKAGE BODY tools IS
  FUNCTION IntMapToList(
    i_map IntMap
  ) RETURN IntList
  IS
    o_list IntList := IntList();
    i      BINARY_INTEGER;
  BEGIN
    IF i_map IS NOT NULL THEN
      i := o_list.FIRST;
      WHILE i IS NOT NULL LOOP
        o_list.EXTEND;
        o_list( o_list.COUNT ) := i_map( i );
        i := i_map.NEXT( i );
      END LOOP;
    END IF;
    RETURN o_list;
  END;
END;
/

CREATE PROCEDURE v1
(
  VehicleGroupID_Array IN tools.IntMap
)
IS
  p_recordset SYS_REFCURSOR;
  p_array     IntList := tools.IntMapToList( VehicleGroupID_Array );
  i           BINARY_INTEGER;
BEGIN
  -- Rest of your procedure using p_array instead of the associative array.
  NULL;
END;
/