【问题标题】:pass array to oracle procedure将数组传递给 oracle 过程
【发布时间】:2011-07-09 02:29:33
【问题描述】:

我想将两个数组从 java 发送到 oracle 存储过程。 第一个数组是字符串数组,第二个是字符数组 我该怎么做??

【问题讨论】:

    标签: java oracle stored-procedures


    【解决方案1】:

    看这里: http://download.oracle.com/docs/cd/B19306_01/java.102/b14355/oraarr.htm#i1058512

    这是我的简短示例:

    1) 在数据库中

    SQL> create or replace type string_array as table of varchar2(100);
      2  /
    
    Type created.
    
    SQL> create or replace function to_string(p_array in string_array) return varchar2
      2  as
      3     l_string varchar2(32767);
      4     i binary_integer;
      5  begin
      6     i := p_array.first();
      7     while i is not null loop
      8        l_string := l_string || p_array(i) || ';';
      9        i := p_array.next(i);
     10     end loop;
     11     l_string := rtrim(l_string, ';');
     12     return l_string;
     13  end;
     14  /
    
    Function created.
    

    2) 在java中

    public class ArrayTest {
        public static void main(String[] args) throws SQLException {
            DriverManager.registerDriver(new OracleDriver());
            OracleConnection connection = (OracleConnection) DriverManager.getConnection(...);
    
            String[] elements = {"abc", "def", "geh"};
            ArrayDescriptor descriptor = ArrayDescriptor.createDescriptor("STRING_ARRAY", connection);
            ARRAY array = new ARRAY(descriptor, connection, elements);
    
            OracleCallableStatement stmt = (OracleCallableStatement) connection.prepareCall("{? = call to_string(?)}");
            stmt.registerOutParameter(1, Types.VARCHAR);
            stmt.setARRAY(2, array);
            stmt.execute();
    
            String result = stmt.getString(1);
            System.out.println("to_string returned: " + result);
        }
    }
    

    似乎有效:输出显示

    to_string returned: abc;def;geh
    

    【讨论】:

      【解决方案2】:

      您可以使用 Oracle 类型将 Java 对象映射到 Oracle。此外,还有 Spring JDBC 实用程序。

      【讨论】:

        【解决方案3】:

        这是一个如何做的例子。

        以下脚本在数据库中设置表、类型和存储过程。该过程采用数组类型的参数并将数组的每一行插入到表中:

        CREATE TABLE strings (s VARCHAR(4000));
        
        CREATE TYPE t_varchar2_array AS TABLE OF VARCHAR2(4000);
        /
        
        CREATE OR REPLACE PROCEDURE p_array_test(
            p_strings      t_varchar2_array
        )
        AS
        BEGIN
          FOR i IN 1..p_strings.COUNT
          LOOP
            INSERT INTO strings (s) VALUES (p_strings(i));
          END LOOP;
        END;
        /
        

        Java 代码随后演示了将数组传递到此存储过程:

        import java.sql.*;
        import oracle.jdbc.*;
        import oracle.sql.*;
        
        public class ArrayTest {
            public static void main(String[] args) throws Exception {
                DriverManager.registerDriver(new OracleDriver());
                Connection conn = DriverManager.getConnection(
                    "jdbc:oracle:thin:@localhost:1521:xe", "user", "pass");
        
                CallableStatement stmt = conn.prepareCall("BEGIN p_array_test(?); END;");
        
                // The first parameter here should be the name of the array type.
                // It's been capitalised here since I created it without using
                // double quotes.
                ArrayDescriptor arrDesc =
                    ArrayDescriptor.createDescriptor("T_VARCHAR2_ARRAY", conn);
        
                String[] data = { "one", "two", "three" };
                Array array = new ARRAY(arrDesc, conn, data);
                stmt.setArray(1, array);
                stmt.execute();
        
                conn.commit();
                conn.close();
            }
        }
        

        如果你运行SQL脚本然后Java类,然后查询表strings,你应该会发现所有的数据都已经插入到表中了。

        当您说“字符数组”时,我猜您的意思是 Java 数组 chars。如果我猜对了,那么我认为您最好将chars 转换为Strings,然后使用与上述相同的方法。

        【讨论】:

        • 多维数组可以做到这一点吗? stackoverflow.com/questions/15045019/…
        • 我已经复制/粘贴了您的整个解决方案 - 导致表“字符串”包含三个(空)值......使用 oracle 9i 以及 10g 和所有可用的 jdbc 驱动程序 - 结果是相同的。 oracle.sql.ARRAY 在 java 中创建时为空 - 我正在尝试找到解决方案,但到目前为止还没有运气:( 与此处 stackoverflow.com/questions/14998299/… 的问题相同
        • @Luke Woodward:我支持你。您能否扩展一下如何将数组列表传递给函数。数据库中的函数不是我创建的,需要传递2个arraylists。
        • @ShirgillAnsari:不,我不明白为什么要这么做。您不知道 ArrayList 上的 toArray() 方法吗?
        【解决方案4】:

        正则表达式解决

        select * from table_a  a where a.col in (select   regexp_substr('SMITH,ALLEN,WARD,JONES','[^,]+', 1, level) from dual
        connect by regexp_substr('SMITH,ALLEN,WARD,JONES', '[^,]+', 1, level) is not null;)
        

        【讨论】:

        • 您是否建议将数组转换为逗号分隔的String 并将其传递给需要varchar2 的过程?然后将其分解回其元素?这看起来很乱,可能会达到 32k 大小限制,并且如果任何值已经包含逗号,则会中断(可能是无声的)......
        【解决方案5】:

        由于 ArrayDescriptor 自 12c 起已弃用,因此不应再使用它。 这是在 12c 中为我工作的代码片段:

                    Array array = ((OracleConnection) connection).createOracleArray("T_VARCHAR2_ARRAY", data);
                    CallableStatement statement = connection.prepareCall("{call p_array_test(?)}");
                    statement.setArray(1, array);
                    statement.execute();
        

        【讨论】:

          【解决方案6】:

          PeudoCode 与我实现的方式相同。

              # 1.You will require a structDescriptor object for an object equivalent in pl sql like :
          
              StructDescriptor structDes= new StructDescriptor("<schemaname in caps>.<sql_object_name>", connectionObject);
          
              # 2. You will need to pass one object values such name, class, id to an object array in order and accordance to 'sql_object_name' object. 
          
              For exmaple:
              STRUCT[] structArray=new STRUCT[<ListObj>.size()];
              int index=0;
              for (a in ListObj){
          
              Object[] object=new Object[]{a.getName(),a.getId()};
              STRUCT struct=new STRUCT(structDes ,connectionObject,object);
                         structArray[index]=struct;
                         index++;
          
              }
          
              ArrayDescriptor arrayDes=ArrayDescriptor.createDescriptor(
                  "<Schema name>.<table object from sql>", connectionObject);
          
              ARRAY array=new ARRAY(arrayDes,connectionObject, structArray);
          
             then pass it to proc 
          
             .declareParameters(
             new SqlInOutParameter("<parameter to proc name>",OracleTypes.ARRAY,"
             <schema name>.<sql_array_or_table_obj>"))
          
             like 
             Hashmap<String, Object> map= new HashMap<>();
             map.put("<parameter to proc name>",array);
             psStatement.execute(map);
          

          希望对您有所帮助。此顺序可能会根据使用的 sql 数据库的要求和类型而有所不同,但基本相同。

          我从我的其他答案之一复制了这个答案。

          Pass array as input parameter to an oracle stored procedure using simple jdbc call

          【讨论】:

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