pass integer array to oracle procedure by c#

前端 未结 2 1846
感动是毒
感动是毒 2020-12-18 16:09

I want to pass an integer array to a stored procedure via c#. the procedure works via sql developer but in c# it doesn\'t work. this is my code but i got stuck by the

相关标签:
2条回答
  • 2020-12-18 17:15

    Your type:

    create or replace TYPE INNUMARRAY AS TABLE OF INTEGER;
    

    is a collection defined in the SQL scope.

    Your passed argument:

    p_strings.CollectionType = OracleCollectionType.PLSQLAssociativeArray;
    p_strings.Value = new int[5]{1,2,3,4,5};
    

    is an associative array which can only be defined in a PL/SQL scope (i.e. in a package or within a PL/SQL block) and cannot be used in an SQL scope.

    They are two different and incompatible data types.

    Instead, you can create an associative array type in a package and then manually extract each value from the associative array into a collection that can be used in the SQL scope:

    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;
    /
    

    can I define the associative array type outside of package? I want them to be standalone.

    No, but you can define a package just containing the type:

    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;
    /
    

    Or, better, create some generically named types and a function in the package to translate from an associative array to a collection and then reuse them in your procedures:

    SQL Fiddle

    Oracle 11g R2 Schema Setup:

    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;
    /
    
    0 讨论(0)
  • 2020-12-18 17:15

    An Associative Array is defined by create or replace TYPE INNUMARRAY AS TABLE OF INTEGER INDEX BY PLS_INTEGER;

    However, you cannot use Associative Arrays in TABLE(...) expression. For this you must convert the Associative Array into a Nested Table (without INDEX BY PLS_INTEGER), for example like this:

    create or replace TYPE VehicleGroupID_TableType AS TABLE OF INTEGER;
    

    ...

    VehicleGroupID_Table VehicleGroupID_TableType  := VehicleGroupID_TableType();
    
    BEGIN
    
        FOR i IN VehicleGroupID_Array.FIRST..VehicleGroupID_Array.LAST LOOP
            VehicleGroupID_Table.EXTEND;
            VehicleGroupID_Table(VehicleGroupID_Table.LAST) := VehicleGroupID_Array(i);
        END LOOP;
    
        ... 
        WHERE  "VehicleGroupDetail"."VehicleGroupID" IN (
           select column_value from table(VehicleGroupID_Table))
         )
    

    or shorter version:

    WHERE  "VehicleGroupDetail"."VehicleGroupID" MEMBER OF VehicleGroupID_Table
    
    0 讨论(0)
提交回复
热议问题