问题
How do I receive a nested table in java from pl/sql procedure's OUT parameter? Here is my example code.
Connection connection = utilities.getConnectionToDb();
CallableStatement callableStatement = connection.prepareCall("{call procedure_name(?,?)}");
callableStatement.setLong(1, 23456);
callableStatement.registerOutParameter(2, Types.ARRAY);
callableStatement.executeQuery();
But when I try executing it I get the error PLS-00306: wrong number or types of arguments in call to 'procedure_name'
I am sure that the number of arguments are correct.
回答1:
This may answer your question
http://asktom.oracle.com/pls/asktom/f?p=100:11:::::P11_QUESTION_ID:8908169959941
I am quoting this from the website above-
SQL> create or replace type numArray as table of number;
2 /
Type created.
SQL> create or replace type dateArray as table of date;
2 /
Type created.
SQL> create or replace type strArray as table of varchar2(255);
2 /
Type created.
SQL> create or replace package demo_passing_pkg
2 as
3 procedure pass( p_in in numArray, p_out out numArray )
4 as language java
5 name 'demo_passing_pkg.pass_num_array( oracle.sql.ARRAY,
6 oracle.sql.ARRAY[] )';
7
8 procedure pass( p_in in dateArray, p_out out dateArray )
9 as language java
10 name 'demo_passing_pkg.pass_date_array( oracle.sql.ARRAY,
11 oracle.sql.ARRAY[] )';
12
13
14 procedure pass( p_in in strArray, p_out out strArray )
15 as language java
16 name 'demo_passing_pkg.pass_str_array( oracle.sql.ARRAY,
17 oracle.sql.ARRAY[] )';
18 end;
19 /
Package created.
SQL> set define off
SQL>
SQL> create or replace and compile
2 java source named "demo_passing_pkg"
3 as
4 import java.io.*;
5 import java.sql.*;
6 import java.math.*;
7 import oracle.sql.*;
8 import oracle.jdbc.driver.*;
9
10 public class demo_passing_pkg extends Object
11 {
12
13 private static void show_array_info( oracle.sql.ARRAY p_in )
14 throws SQLException
15 {
16 System.out.println( "Array is of type " +
17 p_in.getSQLTypeName() );
18 System.out.println( "Array is of type code " +
19 p_in.getBaseType() );
20 System.out.println( "Array is of length " +
21 p_in.length() );
22 }
23
24 public static void pass_num_array( oracle.sql.ARRAY p_in,
25 oracle.sql.ARRAY[] p_out )
26 throws SQLException
27 {
28 show_array_info( p_in );
29 java.math.BigDecimal[] values = (BigDecimal[])p_in.getArray();
30
31 for( int i = 0; i < p_in.length(); i++ )
32 System.out.println( "p_in["+i+"] = " + values[i].toString() );
33
34 Connection conn = new OracleDriver().defaultConnection();
35 ArrayDescriptor descriptor =
36 ArrayDescriptor.createDescriptor( p_in.getSQLTypeName(), conn );
37
38 p_out[0] = new ARRAY( descriptor, conn, values );
39
40 }
41
42 public static void
43 pass_date_array( oracle.sql.ARRAY p_in, oracle.sql.ARRAY[] p_out )
44 throws SQLException
45 {
46 show_array_info( p_in );
47 java.sql.Timestamp[] values = (Timestamp[])p_in.getArray();
48
49 for( int i = 0; i < p_in.length(); i++ )
50 System.out.println( "p_in["+i+"] = " + values[i].toString() );
51
52 Connection conn = new OracleDriver().defaultConnection();
53 ArrayDescriptor descriptor =
54 ArrayDescriptor.createDescriptor( p_in.getSQLTypeName(), conn );
55
56 p_out[0] = new ARRAY( descriptor, conn, values );
57
58 }
59
60 public static void
61 pass_str_array( oracle.sql.ARRAY p_in, oracle.sql.ARRAY[] p_out )
62 throws java.sql.SQLException,IOException
63 {
64 show_array_info( p_in );
65 String[] values = (String[])p_in.getArray();
66
67 for( int i = 0; i < p_in.length(); i++ )
68 System.out.println( "p_in["+i+"] = " + values[i] );
69
70 Connection conn = new OracleDriver().defaultConnection();
71 ArrayDescriptor descriptor =
72 ArrayDescriptor.createDescriptor( p_in.getSQLTypeName(), conn );
73
74 p_out[0] = new ARRAY( descriptor, conn, values );
75
76 }
77
78 }
79 /
Java created.
SQL> set serveroutput on size 1000000
SQL> exec dbms_java.set_output( 1000000 )
PL/SQL procedure successfully completed.
SQL>
SQL> declare
2 l_in strArray := strArray();
3 l_out strArray := strArray();
4 begin
5 for i in 1 .. 5 loop
6 l_in.extend;
7 l_in(i) := 'Element ' || i;
8 end loop;
9
10 demo_passing_pkg.pass( l_in, l_out );
11 for i in 1 .. l_out.count loop
12 dbms_output.put_line( 'l_out(' || i || ') = ' || l_out(i) );
13 end loop;
14 end;
15 /
Array is of type OPS$TKYTE.STRARRAY
Array is of type code 12
Array is of length 5
p_in[0] = Element 1
p_in[1] = Element 2
p_in[2] = Element 3
p_in[3] = Element 4
p_in[4] = Element 5
l_out(1) = Element 1
l_out(2) = Element 2
l_out(3) = Element 3
l_out(4) = Element 4
l_out(5) = Element 5
PL/SQL procedure successfully completed.
回答2:
The way a nested table is recieved from an OUT parameter depends on how the table is nested consider a simple array type
object type
CREATE OR REPLACE
TYPE HR.TNAME
AS
OBJECT( NO1 NUMBER,
NAME VARCHAR2(10)
);
table type
CREATE OR REPLACE
TYPE HR.ITYPE_CUSTOM
IS TABLE OF tname;
Procedure
CREATE OR REPLACE PROCEDURE HR.p_schema_level_out(IN1 IN varchar2,p_det OUT itype_custom)
AS
lc_var itype_custom := itype_custom();
BEGIN
lc_var.extend;
lc_var(1) := TNAME(NO1 => 1,NAME => 'TRAIL1');
lc_var(1).no1 := 1;
lc_var(1).name := 'qwe';
p_det:= lc_var;
END;
/
The above procedure which returns a custom array type can be handled by
try {
stmt = con.createStatement();
// -----------------------------------------------------
// Call PL/SQL Procedure
// -----------------------------------------------------
String s1 = "begin p_schema_level_out(?,?); end;";
cstmt = (OracleCallableStatement) con.prepareCall(s1);
cstmt.setString(1, "something");
cstmt.registerOutParameter(2, Types.ARRAY, "ITYPE_CUSTOM");
cstmt.execute();
Object[] data = (Object[]) ((Array) cstmt.getObject(2)).getArray();
for (Object tmp : data) {
STRUCT row = (STRUCT) tmp;
for (Object attribute : row.getAttributes()) {
System.out.println(attribute);
}
cstmt.close();
stmt.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
This works as a base on how you can recieve a table type i could still help you through if you can post your nested table type
来源:https://stackoverflow.com/questions/12060917/using-nested-tables-in-java