Passing an ARRAY from Java to PL/SQL
Venkatesh, May 07, 2002 - 12:45 pm UTC
Thanks again Tom for your help.
Venkat
A Reader
Rahul, July 31, 2002 - 7:52 am UTC
Hi Tom
I have a small doubt, please clear it.
I have a proecdure which takes the parameter values from a form filled by a user and insert it into a table.
That form has 15 to 20 parameters and right now I am using one IN parameter for each value.
Please tell me, I should use the same approach or use the array for that..which one is better and optimize approach??
Thanks.
August 05, 2002 - 9:35 am UTC
I cannot say -- it depends on the code in the client doesn't it?
Is dealing with the data in an array more natural?
Is dealing with each parameter as a formal named (and typed) parameter more natural?
Performance wise, it'll be 6 one way, 1/2 dozen the other way.
peter, August 07, 2002 - 7:36 am UTC
I think the confusion perhaps lies/lay in why we have two overloaded pass routines and whether that really necessary.
Useful never the less.
What about a more comple array?
Carol, June 09, 2003 - 5:45 pm UTC
I understand your example, but I am unable to understand how to extend it to allow an array containing something like (last_name, first_name, address) to be returned from the java to the pl/sql (I am not querying the database to retrieve the information, I am building the array manually). I cannot find an example on this. Does one exist?
Thank you
June 09, 2003 - 7:08 pm UTC
It is still not clear to me
Carol, June 10, 2003 - 10:30 am UTC
I'm sorry, but the example does not make it clear to me. If I declare a structure like:
create or replace type testemp as object (
fname varchar2(20),
lname varchar2(20))
/
create or replace type testtableemp as table of testemp
/
in PL/SQL. What is the related structure I would declare in my java? I want to populate this structure manually with my java code and pass it back to PL/SQL.
Thanks again.
June 10, 2003 - 10:48 am UTC
you can use jpublisher (way beyond where I'm going...) to map these object types to java classes.
Me, I would juse
create global temporary table gtt ( fname varchar2(20), lname varchar2(20) )
on commit delete rows;
and have the java app BATCH insert into this and then call the procedure, the procedure just uses that tables data as its inputs.
that, in my experience, is the least amount of code between "me" and "being finished"
JPublisher
bob, June 10, 2003 - 12:43 pm UTC
Tom,
No need to go there (JPub that is).. (that is what OTN is for!)
</code>
http://otn.oracle.com/sample_code/tech/java/sqlj_jdbc/files/advanced/advanced.htm <code>
Objects can be accessed either using oracle.sql.STRUCT or by defining custom Java Classes to represent the Oracle Object Type. This sample illustrates access of an Object Type using a java class generated by JPublisher, while retrieval using weakly typed objects (oracle.sql.STRUCT) is illustrated in Object Oracle Sample. Updated on 20-May-2003.
Using this example
Carol, August 21, 2003 - 12:13 pm UTC
Hi Tom,
I used the 'passing the array' portion of this example and it worked great. When I try to run the example as a user that is not the owner of the packages/java and type, I cannot get it to work. Is it possible or am I doing something wrong?
I changed the code to just pass strings (and not arrays so I didn't need the type strarray) and when I run it as a different user it works fine.
Any ideas?
Thanks.
August 21, 2003 - 7:09 pm UTC
not working is 'too vague'
was it "type not known" type of error? did you grant execute on it?
what was the error?
Passing a Java String array from Java to PL/SQL
olerag, August 28, 2003 - 4:52 pm UTC
First example of code I've seen that clearly demos
passing a Java String array to a PL/SQL stored function
that is implemented with a PL/SQL block.
Other examples only showed a Java class that passed an
array to a PL/SQL block only to return it to the same
Java class. This did not provide the "key" to the issue,
specifically the return type as depicted in the PL/SQL
packaged function, "oracle.sql.ARRAY[]".
The reference, however, to JDeveloper was, I suppose, an
attempt to demonstate the capaiblities of passing
multi-dimensional arrays. I wonder how one might return
this type of object (String[][]) to a PL/SQL packaged
function in a pure PL/SQL environment??
August 29, 2003 - 8:41 am UTC
Passing a List Java Collection Type from Java to PL-SQL Java Stored Procedure
pasko, October 07, 2003 - 2:14 pm UTC
Hi Tom,
I have just finished reading the above Great example..
but still couldn't figure out how to pass a List Java Collection Type from java to PL-SQL using java stored Procedure.
For example in java code there's a declaration like :
List results = new ArrayList() ;
I was thinking of copying this List type to an array of String , but may be there's a 1-to-1 mapped Type from List to Oracle jdbc Types .
So , what mapped type should i use in the java stored Procedure.
I would really appreciate your Response on this .
Thanks in advance.
October 07, 2003 - 2:17 pm UTC
you have to use the collection type, as above. you need to map to a SQL type.
Limitation on array size?
Dazza, January 23, 2004 - 4:32 pm UTC
Tom,
when i use the example with 10 elements in the array it works. if i try 11 i get:
ORA-00932: inconsistent datatypes
on the call to the Java.
am i doing something wrong here?
Dazza
A reader, January 23, 2004 - 5:03 pm UTC
Tom,
please ignore that previous comment.
In my java file if one of the elements of the array turns out to be "" (ie a zero length java string) it crashes Oracle. if i put a bit of code that said:
if (arrayInput[i] == ""){arrayInput[i] = null}
the problem goes away.
wierd?
varray
Venkat, February 10, 2004 - 4:32 am UTC
Tom,
Our developeres feel that java API can be used to handle varrays in Java instead of oracle or weblogic API to eliminate dependency of oracle/weblogic on this part.
Is this the best way keeping in view the future implementation of oracle?
Regards,
Venkat
February 10, 2004 - 6:40 am UTC
don't understand what the goal is or how they would remove "what dependency". not sure at all what they mean.
Brilliant
Matthew, April 06, 2004 - 12:08 am UTC
Tom,
Once again you prove to be an absolute godsend. Worked perfectly in both our 8i & 9i databases :)
Only one comment: I can't see what you're illustrating with the 'demo_passing_pkg.pass' example.
The Java side is declared to be String[], but the PL/SQL side is merely "Varchar2", and the result is the Java stored procedure receives a single-element String[].
Is this just to demonstrate a convenient feature of the PL/SQL-Java interface (that single-element arrays can be manipulated without the need for oracle.sql.ARRAY)... or did I miss the real point of that particular example.
cheers,
Matthew
April 06, 2004 - 9:00 am UTC
I was demonstrating IN OUT parameters.
To do "out" you need to use an array so you can change what the array points to.
A Reader
A Reader, April 07, 2004 - 2:20 am UTC
" Performance wise, it'll be 6 one way, 1/2 dozen the other way."
I am not getting it. What does it mean?
April 07, 2004 - 9:08 am UTC
a dozen is 12
1/2 dozen is 6, 6 and 1/2 dozen are the same.
it is a way to say "the same" -- sorry, guess I used an analogy that is not world wide
what if i only want to pass P_OUT OUT STRARRAY from Java to PL/SQL ..
pasko, April 20, 2004 - 3:55 am UTC
Hi Tom,
from the original Post from this thread and examples from your Book ,
you seem to be getting the STRARRAY Type by using the code :
"p_in.getSQLTypeName()"
1.
so, lets assume that i only want to pass an OUT array of Type STRARRAY from Java to PL/SQL, would i still be forced to declare the p_in Variable ?
2.From the code snippet :
PROCEDURE PASS(
P_IN IN STRARRAY , P_OUT OUT STRARRAY
)
AS LANGUAGE JAVA NAME 'demo_passing_pkg.pass_str_array(
oracle.sql.ARRAY , oracle.sql.ARRAY[] )';
that seems to map:
P_IN IN STRARRAY => oracle.sql.ARRAY
P_OUT OUT STRARRAY => oracle.sql.ARRAY[]
although it works fine , i was expecting a Type Mis-match here; can you please elaborate a little bit what's the magic used here , because i thought both P_IN and P_OUT pl/sql variables would have been mapped to : oracle.sql.ARRAY[] and not oracle.sql.ARRAY
Thanks in advance.
April 20, 2004 - 8:41 am UTC
1) no, i was showing an IN and an OUT parameter. p_in and p_out.
if all you have is an OUT, by all means, just use an OUT
2) P_IN is passed by value -- goes right into a string variable. You cannot modify the string value.
P_OUT is passed by reference -- they use an array of strings (the array is imutable, what the array POINTS TO is changeable). We really just modify what the first array element points to and the data is given back to the caller.
Access Isssues/errors when attempting to as another account
olerag, May 27, 2004 - 8:19 pm UTC
Carol's previous statement (08/2003) about grant/access
issues seem relevant. The PL/SQL block that calls the
package and, consequently, the Java class that prepares/
returns the string array, works great for the account that
creates the objects. However, if the block is executed by
another user (even if grants have been issued to that user
for both the type(s) and package), the Oracle exception
originates from the Java class stating that the type,
as specified in the "Descriptor", attempts to alter the
type name to that user's schema (which, of course, the
user doesn't have).
Also, the "getSQLTypeName()" function appears to work with
the oracle.sql.ARRAY object but not the oracle.sql.ARRAY[].
Consequently, if you did not pass this object in your
example (lets say, you used java.lang.string instead), I
believe you would of had to use the type's literal name in
your descriptor in the Java class. Is this correct??
Pass Array from Java to PL/SQL
Alex, August 27, 2004 - 8:50 pm UTC
I am looking for a way to pass string array from Java app via thin JDBC to PL/SQL function that will return status whether DML was successful back to Java.
This app is a batch job it currently executes DML similar to this
UPDATE loan_status SET state = 'Processed'
WHERE tx_id IN ( ?, ?, ?, etc )
IN clause can be very lengthy. I would like to optimize passing java array and bulk binding FORALL etc.
Could you give some simple example how to achieve this? We are using oracle 9.2 on Solaris 8. I was searching in your book and on this web site but could not find the answer.
Your reference </code>
http://asktom.oracle.com/pls/asktom/f?p=100:11:::::P11_QUESTION_ID:712625135727 <code>
Shows example of Java stored procedure how much difference there would be over thin JDBC.
Sorry, I am DBA trying to help java programmers.
You help greatly appreciated.
August 28, 2004 - 9:40 am UTC
if you have "expert one on one oracle" -- the java external routine chapter demonstrates how to easily pass scalars and arrays of scalars between java and plsql. The same method works for java outside of the database as does "inside"
that referenced example above is "perfect" for java in or out of the database.
Another method fro passing Index-By Tables Java-PL/Sql back-and-forth
pasko, August 28, 2004 - 1:17 pm UTC
August 28, 2004 - 3:57 pm UTC
that is plsql index by tables.
it was added in the 8ir3 timeframe.
it works with the THICK oci drivers only. I have examples on this site as well.
Thanks !!!!!
Aparna, April 20, 2005 - 2:26 pm UTC
It helped me a lot to clear my doubts in using varray
Java objects through Callable statements.
Deepak, September 09, 2005 - 12:04 am UTC
Hi Tom,
Can we pass java objects through the Java Callable Statement to PL/SQL Procedures? My requirement is to Catch the object on Oracle side and access it's attributes.
Please help...
September 09, 2005 - 7:01 am UTC
you can pass SQL objects ( create type myTable as object ..... ) to and from java.
But java classes, much like plsql record types, are somewhat "limited to their own language".
You have to map the datatypes to something both languages can understand (SQL datatypes).
What if we dont want to write java code in PL/SQL procedure
Vishal, October 06, 2005 - 12:57 pm UTC
I am trying to pass array (PL/SQL TABLE type) as out parameter through the CallableStatement
CallableStatement cs = con.prepareCall("call RPT_WEB_PKG.TASK_STAGE_ATTRIBUTE(?,?)",ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE);
in JSP file.
The definition of RPT_WEB_PKG.TASK_STAGE_ATTRIBUTE(Task_Id IN NUMBER,Stage_id OUT INT_ARRAY);
where INT_ARRAY is
create or replace type INT_ARRAY is table of number;
I am not sure how to register out parameter in Java.
From the above example I understood that we need to supply Java code in the PL/SQL package. But I dont want to go for it. Is there some other way.
I got some clue as to how to pass it as IN parameter from
</code>
http://asktom.oracle.com/pls/asktom/f?p=100:11:::::P11_QUESTION_ID:712625135727 <code>
Any help would be appreciated.
Thanks
Alex, January 26, 2006 - 11:03 am UTC
Tom or Menon,
Can you pass an Object[] to Oracle consisting of mupltiple data types? Like element 1 might be an integer, 2 might be a string etc? I don't know if Oracle cares how that stuff comes in. Can I use a VARRAY to accept the incoming object array? Thanks.
January 26, 2006 - 11:21 am UTC
ops$tkyte@ORA9IR2> create or replace type myType as table of sys.anyData
2 /
Type created.
ops$tkyte@ORA9IR2>
ops$tkyte@ORA9IR2> declare
2 l_data myType := myType( sys.anyData.convertNumber(5),
3 sys.anyData.convertDate( sysdate ),
4 sys.anyData.convertVarchar2('Hello world' ) );
5 begin
6 null;
7 end;
8 /
PL/SQL procedure successfully completed.
you could have a collection (nested table or varray) of anydata
Alex, January 26, 2006 - 12:04 pm UTC
Tom, Thanks, I'm still having a problem though. Would you mind looking at this?
public class Pass_ObjectArray {
static Connection conn = null;
public static void main(String[] args) throws Exception {
if (conn == null) {
DriverManager.registerDriver(new OracleDriver());
conn = DriverManager.getConnection(
"jdbc:oracle:thin:@none_of_your_business:DEV",
"MY_USER", "MY_PASSWORD");
}
Integer x = 100;
String y = "Object Array";
Object[] arrayObject = { x, y };
ArrayDescriptor descriptor = ArrayDescriptor.createDescriptor(
"MY_USER.PASSING_ARRAY", conn);
ARRAY myArray = new ARRAY(descriptor, conn, arrayObject.toString());
CallableStatement cs = conn
.prepareCall("begin array_test.sp_array_test(?); end;");
cs.setArray(1, myArray);
cs.execute();
conn.close();
}
}
Database code:
CREATE TABLE t2 (mj VARCHAR2(14));
/
CREATE OR REPLACE TYPE passing_array AS TABLE OF VARCHAR2 (1000);
/
CREATE OR REPLACE PACKAGE array_test
AS
PROCEDURE sp_array_test (p_table IN passing_array);
END;
/
CREATE OR REPLACE PACKAGE BODY array_test
AS
PROCEDURE sp_array_test (p_table IN passing_array)
IS
BEGIN
FORALL i IN 1 .. p_table.COUNT
INSERT INTO t2
(mj
)
VALUES (p_table (i)
);
END sp_array_test;
END;
/
Causes this:
Exception in thread "main" java.sql.SQLException: Fail to convert to internal representation: [Ljava.lang.Object;@115273a
at oracle.jdbc.dbaccess.DBError.throwSqlException(DBError.java:134)
at oracle.jdbc.dbaccess.DBError.throwSqlException(DBError.java:179)
at oracle.jdbc.dbaccess.DBError.check_error(DBError.java:1130)
at oracle.jdbc.oracore.OracleTypeCHAR.cArrayToDatumArray(OracleTypeCHAR.java:622)
at oracle.jdbc.oracore.OracleTypeCHAR.toDatumArray(OracleTypeCHAR.java:210)
at oracle.sql.ArrayDescriptor.toOracleArray(ArrayDescriptor.java:1517)
at oracle.sql.ARRAY.<init>(ARRAY.java:117)
at Passing_array.Pass_ObjectArray.main(Pass_ObjectArray.java:48)
Thanks as always.
January 27, 2006 - 8:07 am UTC
you seem to be putting an integer in there? it is a collection of strings?
Alex, January 27, 2006 - 8:44 am UTC
Uh did you see my first question? Does it have to be a collection of the same types? Or maybe I would convert my Object[] to a String[] and pass that? I'm not a java programmer so I don't know which side the problem is coming from.
January 27, 2006 - 8:50 am UTC
Uh, yes I did, but you didn't use the anydata type at all here - so....umm, well - not sure what to say.
right now, you are using varchar2, you asked me yesterday if you could pass an array with a number, a date, a string and I said yes - and showed how to define it. Your current example - it contains nothing from yesterday.
You have a table of varchar2() - that is a table of strings. You would need a table of anydata types and use the anydata methods and (blah blah blah...)
In short, you would need slightly more code, code I don't have an example for offhand. It would be time to involve a java programmer to write the necessary java code to interface with the anydata type, create an ARRAY of that type and pass it to plsql (at which point, they might just realize that maybe we'll just pass "strings" - numbers and dates can be safely converted to a string and it'll be "easy")
Alex, January 27, 2006 - 9:26 am UTC
Sorry I don't know how to incorporate your example into what I'm trying to do so I figured you misunderstood was I was trying to do. I have a dynamic object array that could contain any data type so I don't know how I could call a convertdate, convertnumber on something I won't know until run time what it will be. Do you think it would be best to just use a String[]?
January 27, 2006 - 11:21 am UTC
I would likely just use string to send an array of "some data" - but I don't know everything you are trying to do - but it seems that a java programmer would be required here (else why bother, you either have java to code or not and if you do, you'd have a programmer?)
Alex, January 27, 2006 - 10:58 am UTC
Nevermind I got it working. You can just pass an Object[] and it will work with a VARRAY. I had other issues going on, out of date character set libraries and such. Thanks for the help sorry if I pissed you off.
January 27, 2006 - 11:31 am UTC
No worries - I don't get "pissed off", I just go away :)
Alex, January 27, 2006 - 1:10 pm UTC
Tom,
I'm not quite out of the woods yet. I have one other thing I was hoping you could help me resolve. It turns out I do need sys.anyData. The requirements call for an any type column. So I know I have to create my table column as anydata. I know I have to create the type as anyData.
My problem is, given my procedure with the insert, how do I determine what type each element is to call the appropriate convertxxx function? Some pseudo code would be great. I hope that makes sense.
Alex, January 28, 2006 - 2:43 pm UTC
If that's the case I may try and convince the java developers otherwise. I think I know exactly what you mean about anyData. I could not even get a simple query to run off of my anyData column. You cannot simply do
select * from t where anydata_col = 100
nor did this work
select * from t
where anydata_col = sys.anyData.convertNumber(100)
It looks to be a pain in the neck. Do you have any links or reason you can give me as ammo not to use this? I need to start coming up with alternatives.
January 29, 2006 - 8:13 am UTC
in talking to a java programmer, you might be hitting your head on the proverbial wall. "generic", "obscure", "tricky", "neato-cool", "look how little code, so what if no one understands it" - are tricks of the trade.
Experience trying to use or let end users use the resulting mess is what convinces some of them over time, only some though.
Alex, January 30, 2006 - 10:59 am UTC
Tom how come you didn't cover anydata in your new book in the data types chapter? I'm having a real tough time finding information on it. The documentation is pretty limited.
January 30, 2006 - 3:13 pm UTC
I don't approve of it (could you not tell? :)
I don't think it is a really good idea, so I don't promote it.
Alex, January 30, 2006 - 3:27 pm UTC
Oh I could tell, definitely
Actually what I am looking for is examples of why not to use it. In the past I have seen you mention things you don't like and why. Autonomous transactions in Expert-One-on-One comes to mind. "Here's how you get around mutating tables but if you have to do this there's something wrong with your logic" type of things.
It's important to talk about potentially dangerous stuff like that. Obviously the Oracle docs aren't going to say bad things about their own features and that's where I go to look a lot of stuff up. So people who don't know any better (me for example), aren't going to figure these things out unless experts (you) point it out.
January 30, 2006 - 3:48 pm UTC
In Effective Oracle by Design I have a section entitled
<quote>
Dont Use Generic Data Models
Frequently, I see applications built on a generic data model for maximum flexibility or applications built in ways that prohibit performance. Many times, these are one and the same thing! For example, it is well known you can represent any object in a database using just four tables:
Create table objects ( oid int primary key, name varchar2(255) );
Create table attributes
( attrId int primary key, attrName varchar2(255),
datatype varchar2(25) );
Create table object_Attributes
( oid int, attrId int, value varchar2(4000),
primary key(oid,attrId) );
Create table Links ( oid1 int, oid2 int,
primary key (oid1, oid2) );
Thats it. No more CREATE TABLE for me!....
</quote>
Perhaps the closest I come to that - well, short of the section:
<quote>
Use the Correct Datatype
Using the correct datatype seems like common sense, but virtually every system I look at does one of the following:
· Uses a string to store dates or times
· Uses a string to store numbers
· Uses VARCHAR2(4000) to store all strings.
· Uses CHAR(2000) to store all strings, wasting tons of space and forcing the use of a lot of trim function calls
· Puts text in a BLOB (raw) type
I have a very simple rule: Put dates in dates, numbers in numbers, and strings in strings. Never use a datatype to store something other than what it was designed for, and use the most specific type possible. Furthermore, only compare dates to dates, strings to strings, and numbers to numbers.
...
</quote>
put those two together and you have it.
String Array output in Ascii (hex) format !!
Vincent, February 13, 2006 - 7:59 am UTC
Hi Tom,
I have a peculiar problem regarding String array used as output parameter in stored procedures. I have compiled the stored procedure below.
CREATE OR REPLACE TYPE CENAME_ARRAY IS TABLE OF VARCHAR2(25);
CREATE OR REPLACE PROCEDURE GETKBNAMES(FDID IN NUMBER, KBNAMEARRAY OUT CENAME_ARRAY)
AS
KBNAME VARCHAR2(80);
CURSOR KBCE_CUR IS
SELECT KB_NAME FROM KNOWLEDGE_BASE WHERE FD_ID=FDID;
BEGIN
KBNAMEARRAY := CENAME_ARRAY();
OPEN KBCE_CUR;
LOOP
FETCH KBCE_CUR INTO KBNAME;
EXIT WHEN KBCE_CUR%NOTFOUND;
KBNAMEARRAY.EXTEND;
KBNAMEARRAY(KBNAMEARRAY.LAST) := KBNAME;
END LOOP;
CLOSE KBCE_CUR;
END ;
When I test it in sql/plus using the code below, it is giving me the the correct output
DECLARE
FDID NUMBER := 1;
KBNAMEARRAY CENAME_ARRAY;
BEGIN
GETKBNAMES(FDID,KBNAMEARRAY);
FOR K IN KBNAMEARRAY.FIRST..KBNAMEARRAY.LAST
LOOP
DBMS_OUTPUT.PUT_LINE(KBNAMEARRAY(K));
END LOOP;
END;
second kbase
small kbase
but when I access it using a small java program, it is giving me the hex ascii equivalent of the string array above like
"0x7365636F6E64206B62617365"
"0x736D616C6C206B62617365"
I have tested my java code with other schemas and it's working properly.
A snapshot of my java code is as follows
String[] kbnamearray = null;
try {
int fdid = 1;
Class.forName(driver);
conn = DriverManager.getConnection(url_to_pass,username_to_pass,password_to_pass);
String query = "call GETKBNAMES(?,?) ";
ArrayDescriptor descriptor = ArrayDescriptor.createDescriptor( "CENAME_ARRAY", conn );
ARRAY array_to_pass = new ARRAY(descriptor, conn, kbnamearray);
cstmt = conn.prepareCall(query);
cstmt.setInt(1, fdid);
cstmt.registerOutParameter(2,OracleTypes.ARRAY,"CENAME_ARRAY");
cstmt.execute();
kbnamearray =(String[])cstmt.getArray(2).getArray();
thanks
February 13, 2006 - 9:52 am UTC
got a 100% complete, yet very concise example, that has everything one would need to reproduce with.
From start to finish (you can make it very very small - I do all of the time :)
Passing array to Oracle using Standard JDBC, not Oracle JDBC driver
Charlie Zhu, February 13, 2006 - 12:24 pm UTC
Hi Tom,
I would like to know if it's possible to pass Array from Java to Oracle using Sun Standard JDBC Driver,
such as: i-net Oranxo
</code>
http://www.inetsoftware.de/products/jdbc/oracle/oranxo/ <code>
How to make a data type that Java and Oracle both recognise?
There is not a Method/Function like,
ArrayDescriptor desc = ArrayDescriptor.createDescriptor("NUMBERTABLE",
conn);
Thanks a lot.
February 13, 2006 - 12:52 pm UTC
then probably not - it would be a question for the makers of the Sun Standard JDBC driver to answer.
I doubt it though.
Since jdbc drivers are pretty much "free", why wouldn't you use the one that provides you all of the functionality against Oracle?
Re: String Array output in Ascii (hex) format !!
Vincent, February 13, 2006 - 2:37 pm UTC
Hi Tom,
I don't understand your reply regarding the strange output that I am getting from the stored procedure. I suspect it might have something to do with the character set. It only happens when I used String array(table of varchar2) as output parameters. With table of numbers as output, it's working properly.
cheers
February 13, 2006 - 3:11 pm UTC
my reply was simply:
give me the full example that I can cut, paste, run, reproduce.
Do you know what is the limit on argument size passed to JDBC CallableStatement.setObject()?
Ranko Mosic, February 14, 2006 - 1:00 pm UTC
Regards, Ranko
February 14, 2006 - 2:11 pm UTC
should only be limited by the amount of available memory - are you hitting some limit? I'm not aware of any documented limits but if you have the error stack from a failure and think it is size related - we can probably plug it into metalink and see what we see.
Standard JDBC, not Oracle JDBC driver
Charlie Zhu, February 14, 2006 - 2:46 pm UTC
It's a long story.
Before I join this company.
They hit Transaction Process bugs with Oracle JDBC driver
(Oracle 8 or 9), and Oracle Support response was slow,
(Because it's a free product :) ), so they turned to i-net Oranxo JDBC driver, and used it for 3 to 5 years.
It's hard to persuade our Java Developer to turn back to Oracle JDBC driver, it's a 24*7 production system, Voodoo!
and we Chinese say:
'After once you was bited by a snake, you will look all kinds of line/rope as snake and get scared for 10 years'
It's kind of conventional wisdom.
Thanks,
Charlie
Charlie u r right
Leela, February 17, 2006 - 7:47 am UTC
Yes As you told once we strict to one platform. Its very difficult to shift to new tools and environments.
In my case i was trained in java/j2ee but working in datawarehousing.
without Using SQLLODER HOW CAN we retrieve data from Excel ?
A Reader, September 01, 2008 - 7:47 am UTC
Hi Tom,
How Can we Retrieve data from Excel with Out using SQLLOADER.
MIne is Oracle JDeveloper Machine
Using ARRAY AS COLUMNS IN TABLE
A reader, September 16, 2008 - 2:22 am UTC
Hi Tom,
I know that we can insert an array into a table.like this
1.create table sample(msg varchar2(10));
2.create or replace Type numarray is table of varchar2(10);
3.PROCEDURE ARR (W numarray)
IS
BEGIN
for i in 1 .. 5
loop
insert into sample values(W(i));
end loop;
NULL;
END;
If I Excute the procedure like this I am getting the output.
4.declare
data numArray := numarray('1','2','3','4','5');
begin
ARR(data);
end;
If I Run the procedure I am getting Intialization error like this,
DECLARE
W IMD_SAMPLE.NUMARRAY;
BEGIN
-- Modify the code to initialize the variable
-- W := NULL;
IMD_SAMPLE.ARR(
W => W
);
END;
ERROR:
Connecting to the database imd_sample.
ORA-06531: Reference to uninitialized collection
ORA-06512: at "IMD_SAMPLE.ARR", line 6
ORA-06512: at line 7
Process exited.
Disconnecting from the database imd_sample.
Q1.How can I intialise array in stored procedure?
Q2.I need to insert array into a table like this
create table sample(A varchar2(10),B varchar2(10),C varchar2(10,D Varchar2(10),E Varchar2(10),Msg Varchar2(10));
A=>array 1st value;W(1)
B=>Array 2nd value;W(2)
.
.
.
msg='hyd'.
How can I insert this array into above table.?
Thanks in Advance
September 16, 2008 - 10:26 pm UTC
it is not the invoking code, it is the code handling the parameter - it should check for NULL-ness before accessing the elements if it permits NULL to be sent...
and use forall, not for loops, to bulk insert!
ops$tkyte%ORA10GR2> create table sample ( x varchar2(10) );
Table created.
ops$tkyte%ORA10GR2>
ops$tkyte%ORA10GR2> create or replace Type numarray is table of varchar2(10);
2 /
Type created.
ops$tkyte%ORA10GR2>
ops$tkyte%ORA10GR2> create or replace PROCEDURE ARR (W numarray)
2 IS
3 BEGIN
4 if ( w is not null and w.count > 0 )
5 then
6 forall i in 1 .. w.count
7 insert into sample values(W(i));
8 end if;
9 END;
10 /
Procedure created.
ops$tkyte%ORA10GR2>
ops$tkyte%ORA10GR2> declare
2 data numArray := numarray('1','2','3','4','5');
3 begin
4 ARR(data);
5 end;
6 /
PL/SQL procedure successfully completed.
ops$tkyte%ORA10GR2>
ops$tkyte%ORA10GR2> DECLARE
2 W NUMARRAY;
3 BEGIN
4 ARR( W => W );
5 END;
6 /
PL/SQL procedure successfully completed.
How can we intialise array parameters in stored procedure at run time
A reader, September 17, 2008 - 2:33 am UTC
Thank You Tom For the Array procedue,
But what I need is 1.To initialise parameters in stored procedure at run time.In below code where can we give the values to an array.
DECLARE
W NUMARRAY;
BEGIN
ARR(
W => W
);
END;
2.How can we insert an array into a table as column wise
Let array with values 1,2,3,4,5 & the table sam with the columns A,B,C,D,E,MSG
& the procedure is
declare
data numArray := numarray('1','2','3','4','5');
begin
ARR(data,'hyd');
end;
Then the expected output should be like this
A B C D E MSG
1 2 3 4 5 hyd
How can we write a procedure to get above output .Please help me.
Thank you
September 17, 2008 - 9:05 am UTC
declare
w numarray := numarray();
begin
.... start using w, w.extend and w(1) := whatever ....
It seems you already know how to initialize??? Your #2 point shows that already??
it seems rather straightforward to do the insert:
insert into t (a,b,c,d,e,msg) values ( w(1), w(2), w(3), w(4), w(5), w(6) );
you just reference the i'th array position?
You know, it doesn't seem right to use an array for that however, you should use formal named and typed parameters - the invoker should be passing a, b, c, d, e, msg - NOT an array.
Parameter as a Column
A Reader, October 30, 2008 - 6:43 am UTC
Hi Tom,
My table is:
create table tablename(SNO NUMBER(38),NAME VARCHAR2(40),CMV BLOB,WVW BLOB,OLR BLOB,QPE BLOB,CTTI BLOB,GPS BLOB,SYS_DATE DATE);
My Procedure is this: But this procedure is working fine.
PROCEDURE SAT (
P_NAME VARCHAR2,
P_TYPE VARCHAR2,
P_RET_VAL OUT BLOB
)
AS
V_SYS_DATE1 DATE;
V_SYS_DATE2 DATE;
BEGIN
SELECT MAX(SYS_DATE) INTO V_SYS_DATE1 FROM INSAT_SAT_DET_MSTR WHERE TRIM(SAT_NAME) = 'INSAT-3A';
SELECT MAX(SYS_DATE) INTO V_SYS_DATE2 FROM INSAT_SAT_DET_MSTR WHERE TRIM(SAT_NAME) = 'INSAT-3B';
IF P_TYPE = 'CMV' THEN
SELECT CMV INTO P_RET_VAL FROM INSAT_SAT_DET_MSTR
WHERE SYS_DATE = V_SYS_DATE1 AND NAME = P_NAME;
ELSIF P_TYPE = 'WVW' THEN
SELECT WVW INTO P_RET_VAL FROM INSAT_SAT_DET_MSTR
WHERE SYS_DATE = V_SYS_DATE1 AND NAME = P_NAME;
ELSIF P_TYPE = 'OLR' THEN
SELECT OLR INTO P_RET_VAL FROM INSAT_SAT_DET_MSTR
WHERE SYS_DATE = V_SYS_DATE1 AND NAME = P_NAME;
ELSIF P_TYPE = 'QPE' THEN
SELECT QPE INTO P_RET_VAL FROM INSAT_SAT_DET_MSTR
WHERE SYS_DATE = V_SYS_DATE1 ANDNAME = P_NAME;
ELSIF P_TYPE = 'CTTI' THEN
SELECT CTTI INTO P_RET_VAL FROM INSAT_SAT_DET_MSTR
WHERE SYS_DATE = V_SYS_DATE1 AND NAME = P_NAME;
ELSIF P_TYPE = 'GPS' THEN
SELECT GPS INTO P_RET_VAL FROM INSAT_SAT_DET_MSTR
WHERE SYS_DATE = V_SYS_DATE1 AND NAME = P_NAME;
END IF;
END;
My requirement is this can we write a procedure like this if possible give me sample code.
PROCEDURE SAT (
P_NAME VARCHAR2,
P_TYPE VARCHAR2,
P_RET_VAL OUT BLOB
)
AS
V_SYS_DATE1 DATE;
V_SYS_DATE2 DATE;
BEGIN
SELECT MAX(SYS_DATE) INTO V_SYS_DATE1 FROM INSAT_SAT_DET_MSTR WHERE TRIM(SAT_NAME) = 'INSAT-3A';
SELECT MAX(SYS_DATE) INTO V_SYS_DATE2 FROM INSAT_SAT_DET_MSTR WHERE TRIM(SAT_NAME) = 'INSAT-3B';
SELECT P_TYPE INTO P_RET_VAL FROM INSAT_SAT_DET_MSTR
WHERE SYS_DATE = V_SYS_DATE1 AND NAME = P_NAME;
Thanks in Advance.
October 30, 2008 - 8:51 am UTC
v_sys_date2 is never used, lose it.
why this is more than a single query is beyond me.
ops$tkyte%ORA10GR2> create table insat_sat_det_mstr
2 (SNO NUMBER(38),NAME VARCHAR2(40),CMV BLOB,WVW BLOB,OLR
3 BLOB,QPE BLOB,CTTI BLOB,GPS BLOB,SYS_DATE DATE, sat_name varchar2(30));
Table created.
ops$tkyte%ORA10GR2>
ops$tkyte%ORA10GR2>
ops$tkyte%ORA10GR2> create or replace PROCEDURE SAT (
2 P_NAME VARCHAR2,
3 P_TYPE VARCHAR2,
4 P_RET_VAL OUT BLOB
5 )
6 AS
7 BEGIN
8 select decode( p_type, 'CMV', cmv, 'WVW', wvw, 'OLR', olr, 'QPE', qpe, 'CTTI', ctti, 'GPS', gps )
9 into p_ret_val
10 from insat_sat_det_mstr
11 where name = p_name
12 and sys_date = (select max(sys_date) from insat_sat_det_mstr where trim(sat_name) = 'INSAT-3A' );
13 END;
14 /
Procedure created.
No, you cannot do it the way you described (it would require dynamic sql - but
DO NOT EVEN DREAM OF DOING THAT, DO NOT GO THAT PATH, DO NOT)Couple of issues I have
a) obviously, someone meant to have two tables and the blobs would be rows in a separate child table.
It should be
create table parent
( sno primary key,
name,
sys_date,
sat_name check sat_name=trim(sat_name) );
create table child
( sno references parent,
blob_name,
the_blob );
and then you would just join - no decodes, simple.
b) that trim(sat_name) - horrible, it shouldn't be there. You mean to verify the data upon input and make sure it is valid data already. You should definitely change that.
Re: blobs in a separate child table
Stew Ashton, October 30, 2008 - 1:03 pm UTC
Tom, a schema in my shop has this "parent table + child table for the blob" setup. Do you think this is a good idea, given that there will be few entries with blobs? There is nothing in the child table but the blob and the date it was uploaded.
I gathered that the point was to put the blobs in a separate tablespace, but that can be done without having two tables. I can't think of a good reason to have two tables; am I missing something?
Thanks again for everything :)
November 02, 2008 - 3:27 pm UTC
hahahahah
ask your "shop" if they realize that blobs are already in a child table (we call it a lob segment).
AND THEY CONTROL THE TABLESPACES!!!! they can have the blob be in another tablespace already, without this child table.
A lob locator is a pointer. You can either have blobs
a) inline - upto 4000 bytes (like a varchar2 size) would be stored in the table with extremely huge performance gains in most all cases. When it grows over 4000 bytes, a pointer is left behind (the lob locator) and a lob segment is used
b) disable storage inline, we do not use the 4000 byte limit, we out of line it, we always point to another table.
So, all they have done is add extra IO an extra storage. That is, they have only made things absolutely, definitely slower and more storage consuming than they were before. They have done nothing good, they have only done bad.
Well, at least you got a good laugh out of it :)
Stew Ashton, November 02, 2008 - 6:12 pm UTC
Very clear, very concise, very helpful. Thanks!
Passing arrays from java to sql ...
Dave, November 04, 2008 - 4:34 pm UTC
Object Passing to Store Procedure from java
shashi wagh, February 08, 2010 - 4:05 am UTC
Hi
How do I pass Java object from Java to Oracle
Say I have
EmpBean Class with empId, empName, empDept.
I want to pass EMpBean object to Store Procedure and Use It
Please Help.................................................
February 15, 2010 - 10:03 am UTC
that would be a java object - which java understands completely - but no other language does.
You can use a SQL object type - which every language can interface to, since there are documented API's and specifications to do so.
http://docs.oracle.com/docs/cd/B19306_01/java.102/b14188/toc.htm
A reader, March 04, 2010 - 4:59 pm UTC
Interestingly in your example the method pass(String l_in, String[] l_out) doesn't seem to be working.
Example:
DECLARE
L_OUT STRARRAY := STRARRAY ();
l_in varchar2(100):='Testing';
BEGIN
DEMO_PASSING_PKG.PASS (l_in, L_OUT);
FOR I IN 1 .. L_OUT.COUNT
LOOP
DBMS_OUTPUT.PUT_LINE ('l_out('|| I || ') = ' || L_OUT (I));
END LOOP;
END;
/
ERROR at line 11:
ORA-06550: line 11, column 4:
PLS-00306: wrong number or types of arguments in call to 'PASS'
ORA-06550: line 11, column 4:
PL/SQL: Statement ignored
I have a requirement to pass strings and get String[] back, without connecting to Database. This would be a perfect example if it works for me. Thanks in advance.
March 05, 2010 - 5:19 am UTC
please give the entire example, as I did.
I took the original source posted above
I cut that source
I added a "/" after the create or replace java bit that seems to be missing.
I ran it (successfully I might add) in 9ir2, 10gr2, 11gr2.
So, give FULL example and relate your version and we'll try to see what you missed during the cut and paste.
ops$tkyte%ORA11GR2> CREATE OR REPLACE TYPE STRARRAY AS TABLE OF VARCHAR2 (255)
2 /
Type created.
ops$tkyte%ORA11GR2>
ops$tkyte%ORA11GR2> CREATE OR REPLACE PACKAGE DEMO_PASSING_PKG
2 AS
3 -- Varchar2's are most easily mapped to the java String type
4 PROCEDURE PASS (
5 P_IN IN VARCHAR2,
6 P_OUT OUT VARCHAR2)
7 AS
8 LANGUAGE JAVA
9 NAME 'demo_passing_pkg.pass( java.lang.String,
10 java.lang.String[] )';
11
12 PROCEDURE PASS (
13 P_IN IN STRARRAY,
14 P_OUT OUT STRARRAY)
15 AS
16 LANGUAGE JAVA
17 NAME 'demo_passing_pkg.pass_str_array( oracle.sql.ARRAY,
18 oracle.sql.ARRAY[] )';
19
20 FUNCTION RETURN_STRING
21 RETURN VARCHAR2
22 AS
23 LANGUAGE JAVA
24 NAME 'demo_passing_pkg.return_string() return
25 java.lang.String';
26 END DEMO_PASSING_PKG;
27 /
Package created.
ops$tkyte%ORA11GR2>
ops$tkyte%ORA11GR2>
ops$tkyte%ORA11GR2>
ops$tkyte%ORA11GR2> SET define off
ops$tkyte%ORA11GR2>
ops$tkyte%ORA11GR2> 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 public static void pass( java.lang.String p_in,
13 java.lang.String[] p_out ){
14
15 /*
16 * the simplest of datatypes -- the String. If you remember
17 * the C version with 6 formal parameters, null indicators,
18 * strlen's, strcpy's and so on -- this is trivial in
19 * comparision
20 */
21
22 if ( p_in != null ){
23
24 System.out.println
25 ( "The first parameter is " + p_in.toString() );
26
27 p_out[0] = p_in.toUpperCase();
28
29 System.out.println
30 ( "Set out parameter to " + p_out[0].toString() );
31 }
32 }
33
34 private static void show_array_info( oracle.sql.ARRAY p_in )
35 throws SQLException{
36
37 System.out.println( "Array is of type " +
38 p_in.getSQLTypeName() );
39 System.out.println( "Array is of type code " +
40 p_in.getBaseType() );
41 System.out.println( "Array is of length " +
42 p_in.length() );
43 }
44
45 public static void
46 pass_str_array( oracle.sql.ARRAY p_in, oracle.sql.ARRAY[] p_out )
47 throws java.sql.SQLException,IOException{
48
49 show_array_info( p_in );
50 String[] values = (String[])p_in.getArray();
51
52 for( int i = 0; i < p_in.length(); i++ )
53 System.out.println( "p_in["+i+"] = " + values[i] );
54
55 Connection conn = new OracleDriver().defaultConnection();
56 ArrayDescriptor descriptor =
57 ArrayDescriptor.createDescriptor( p_in.getSQLTypeName(), conn );
58
59 p_out[0] = new ARRAY( descriptor, conn, values );
60
61 }
62
63 public static String return_string(){
64 return "Hello World";
65 }
66
67 }
68 /
Java created.
ops$tkyte%ORA11GR2>
ops$tkyte%ORA11GR2>
ops$tkyte%ORA11GR2> SET serveroutput on size 1000000
ops$tkyte%ORA11GR2> EXEC dbms_java.set_output( 1000000 )
PL/SQL procedure successfully completed.
ops$tkyte%ORA11GR2>
ops$tkyte%ORA11GR2> DECLARE
2 L_IN STRARRAY := STRARRAY ();
3 L_OUT STRARRAY := STRARRAY ();
4 BEGIN
5 FOR I IN 1 .. 5
6 LOOP
7 L_IN.EXTEND;
8 L_IN (I) := 'Element ' || I;
9 END LOOP;
10
11 DEMO_PASSING_PKG.PASS (L_IN, L_OUT);
12
13 FOR I IN 1 .. L_OUT.COUNT
14 LOOP
15 DBMS_OUTPUT.PUT_LINE ('l_out('|| I || ') = ' || L_OUT (I) );
16 END LOOP;
17 END;
18 /
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.
A reader, March 05, 2010 - 11:34 am UTC
Here I used stripped version of your code.
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 -- Varchar2's are most easily mapped to the java String type
4 PROCEDURE PASS (
5 P_IN IN VARCHAR2,
6 P_OUT OUT VARCHAR2)
7 AS
8 LANGUAGE JAVA
9 NAME 'demo_passing_pkg.pass( java.lang.String,
10 java.lang.String[] )';
11 END DEMO_PASSING_PKG;
12 /
Package created.
CTPD> CREATE OR REPLACE AND COMPILE JAVA SOURCE NAMED "demo_passing_pkg"
2 AS
3 import java.io.*;
4 import java.sql.*;
5 import java.math.*;
6 import oracle.sql.*;
7 import oracle.jdbc.driver.*;
8 public class demo_passing_pkg extends Object{
9 public static void pass( java.lang.String p_in, java.lang.String[] p_out ){
10 /* the simplest of datatypes -- the String. If you remember
11 * the C version with 6 formal parameters, null indicators,
12 * strlen's, strcpy's and so on -- this is trivial in
13 * comparision
14 */
15 String[] names = new String[5];
16 if ( p_in != null ){
17 System.out.println
18 ( "The first parameter is " + p_in.toString() );
19 names[0] = p_in.toUpperCase();
20 names[1]="Testing Line2";
21 names[2]="Testing Line3";
22 System.out.println ( "Set out parameter to " + names[0].toString() );
23 p_out=names;
24 }
25 }
26 }
27 /
Java created.
Now
1.How do I implement DEMO_PASSING_PKG.PASS ??
2. How do I pass String[] (Array of Strings) back to Oracle. Mapping this java to IN Varchar2, OUT Varchar2 doesn't seem to be right.
3. How do I dynamically expand "names" and still at the end assign "names" to "p_out"(OUT parameter).
March 05, 2010 - 11:47 am UTC
umm, would you take about 5 seconds and review your code. The mistake you have made is actually fairly obvious.
Look at the type you define - strarray.
Now, look at the stripped down package spec you wrote.
Do you see strarray anywhere in there?
Oh, how I .... it when people do things like this and write:
... Interestingly in your example the method pass(String l_in, String[] l_out) doesn't seem to be
working.
...
Not mentioning that they *heavily modified the code in question*. Not even mentioning it. It turns out to be the case pretty much 100% of the time - that they have modified it - a lot.
Please, back up a second, take the original example, make sure you understand all of the bits of it (you don't yet, basing that on the comment #2 you made - you are right, it doesn't make sense to use a varchar2 - you wanted an ARRAY of strings....)
A reader, March 05, 2010 - 11:37 am UTC
My Version of Oracle 10gR2
ORA-00932: inconsistent datatypes
Tyrone Post, March 10, 2010 - 2:36 pm UTC
Hi Tom,
The information on your site has been very helpful. However I was wondering if you could help me with one tiny issue.
I'm attempting to use a java stored procedure to read a file from a remote server into a string array, and pass that array up to PL/SQL as an out parameter so that other functions and procedures can manipulate the data, format it, and insert it into various tables etc etc...
The code that I have written is similar to the code you have provided.
My PL/SQL code:
create or replace type STRARRAY as table of varchar2(32767);
/
create or replace package RF is
procedure read( location varchar2
, fileName varchar2
, arry_in IN strarray
, arry_out OUT strarray );
end RF;
/
create or replace package body RF is
procedure read( location varchar2
, fileName varchar2
, arry_in IN strarray
, arry_out OUT strarray )
is language java
name 'RFile.read(java.lang.String, java.lang.String, oracle.sql.ARRAY, oracle.sql.ARRAY[])';
end RF;
/
My Java Code:
create or replace and compile java source named rfile as
import java.io.*;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.ArrayList;
import oracle.sql.*;
import oracle.jdbc.OracleDriver;
public class RFile {
public static void read(String location, String fileName,
oracle.sql.ARRAY p_in, oracle.sql.ARRAY[] p_out)
throws IOException, SQLException {
BufferedReader br;
FileReader fr = new FileReader(location + "\\" + fileName);
br = new BufferedReader(fr);
ArrayList a = new ArrayList();
String line;
while ((line = br.readLine()) != null) {
a.add((String) line);
}
String[] values = new String[a.size()];
for (int i = 0; i < values.length; i++) {
values[i] = (String) a.get(i);
if (values[i] == "")
values[i] = null;
}
Connection conn = new OracleDriver().defaultConnection();
ArrayDescriptor descriptor = ArrayDescriptor.createDescriptor(p_in.getSQLTypeName(), conn);
p_out[0] = new ARRAY(descriptor, conn, values);
}
}
/
Here is a test script that I've used which reads the file from the local machine:
SET serveroutput on size 1000000
EXEC dbms_java.set_output( 1000000 )
declare
arry_in strarray := strarray();
arry_out strarray := strarray();
begin
rf.read('C:\oracle\io', 'io.dat', arry_in, arry_out);
for i in 1 .. arry_out.count
loop
dbms_output.put_line('arry_out(' || i || ') = ' || arry_out(i) );
end loop;
end;
/
Now the weird thing about this is, when I run it on an oracle installation running on a fellow developers box, it works perfectly. When I run it on an oracle installation on a database test box, it works perfectly. However, when I try to run it on our actual development box, I get the following error:
ORA-00932: inconsistent datatypes: expected an OUT argument at position 4 that is an instance of a user defined Java class convertible to an Oracle type got an object that could not be converted
Now there are some differences between the installations.
Here's the information on the two boxes the procedure did work:
MS Windows XP Professional SP 3
Oracle Release 10.2.0.1
MS Windows Server 2003 R2
Oracle Release 10.2.0.1
(both 32 bit)
Here is the information for the box it did not work under:
MS Windows Server 2003 R2 Enterprise x64 Edition SP2
Oracle Release 10.2.0.4
I'm not sure if the inconsistent behavior is related to these differences but I thought it might be worth mentioning.
Thanks in advance,
Tyrone
March 11, 2010 - 8:09 am UTC
I didn't read the code, I'll just tell you how I would do this.
why use java, you have to have access to the file on the server (even java does) so we can use external tables. Just use an external table. If a java stored procedure can read it, so can a plsql stored procedure, so can an external table. You are doing this the hard way.
Thanks and Note to Others
Tim Jowers, March 11, 2010 - 6:48 am UTC
Thanks for the good depth article. Best on the web. A note to others is the original post is using the defined PROCEDURE "PASS" with the STRARRAY. See, it gets redefined in the first several lines of the example. so, the calling example near the end
DEMO_PASSING_PKG.PASS (L_IN, L_OUT);
is using that second proc definition. So, the question about the String versus String[] mapping to VARCHAR versus STRARRAY may lead you down a misleading path. Looks like the mapping is what you would expect but maybe Oracle doesn't have overloading of PROCEDURE names based on datatype.
A reader, March 23, 2010 - 11:22 pm UTC
String Array output in Ascii (hex) format !!
Harold, May 05, 2010 - 6:24 am UTC
Hi Tom,
I have the same problem especified by Vincent in this post
http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:3696816290928#56953050569757 My full code example:
CREATE or REPLACE TYPE EMPARRAY is VARRAY(3) of VARCHAR2(30)
CREATE or REPLACE FUNCTION EXAMPLE RETURN EMPARRAY
AS
l_data EmpArray := EmpArray();
--declare
type t_tabla is table of varchar2(10);
v_tabla t_tabla:= t_tabla ('A28057537','B91364737','A08924599');
-- declaration variables
conta_pdte_mat number:= 0;
conta_mat number:= 0;
begin
for i in 1 .. v_tabla.count
loop
--
select count(distinct pp.id_peticion)
into conta_pdte_mat
from peticiones_planes pp,
peticiones pet,
planes pl
where pp.id_peticion = pet.id_peticion
and pl.id_plan = pp.id_plan
and pp.id_plan = 0 --MITyC
and pet.fecha_creacion between to_date ('31/03/2010','dd/mm/yyyy') and to_date ('28/04/2010','dd/mm/yyyy')
and pet.cif_nif = v_tabla(i)
and exists (select null
from historico_estados hist
where hist.id_estado = 20
and hist.id_peticion = pet.id_peticion
and hist.id_plan = pp.id_plan
);
--
select count(distinct pp.id_peticion)
into conta_mat
from peticiones_planes pp,
peticiones pet,
planes pl
where pp.id_peticion = pet.id_peticion
and pl.id_plan = pp.id_plan
and pp.id_plan = 0 --MITyC
and pet.fecha_creacion between to_date ('31/03/2010','dd/mm/yyyy') and to_date ('28/04/2010','dd/mm/yyyy')
and pet.cif_nif = v_tabla(i)
and exists (select null
from historico_estados hist
where hist.id_estado = 10
and hist.id_peticion = pet.id_peticion
and hist.id_plan = pp.id_plan
);
--
l_data.extend;
l_data(i) := (v_tabla(i)||';'||conta_pdte_mat||';'||conta_mat);
--
end loop;
return l_data;
END EXAMPLE;
example of one element of the array --> A28057537;419;518
package generaExcel.agentesDeVentas;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import oracle.jdbc.OracleCallableStatement;
import oracle.jdbc.OracleTypes;
import oracle.sql.ARRAY;
public class ExcelEvolucionExpedientesAV {
public static void main(String[] args){
Connection cn = null;
OracleCallableStatement stm = null;
try{
DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver());
cn = DriverManager.getConnection(url, user, password);
stm = (OracleCallableStatement)cn.prepareCall("begin ? := EVOLUCION_EXPEDIENTES_AV;end;");
stm.registerOutParameter(1, OracleTypes.ARRAY, "EMPARRAY");
stm.executeUpdate();
ARRAY simpleArray = stm.getARRAY(1);
String[]list = (String[])simpleArray.getArray();
for(String s: list)
System.out.println(s);
}catch(SQLException sqle){
System.out.println(sql.getMessage());
}finally{
try{
if(stm != null)
stm.close();
if(cn != null)
cn.close();
}catch(SQLException sqle){
System.out.println(sql.getMessage());
}
}
}
}
the console shows 0x4132383035373533373B3431393B353138 instead A28057537;419;518
Do you know why it can happen?
Thanks
PD: My english is not very well, sorry
May 06, 2010 - 2:00 pm UTC
I don't have your tables.
I therefore cannot run your code.
Perhaps you should code the plsql example in a manner that doesn't require any tables so I can run the example from start to finish?
Passing List of records to the Oracle Procedure
Mohammad, March 09, 2011 - 2:49 am UTC
Hello Tom,
Firstly, I would like to thank you a lot for helping people.
I am tring to send list of objects to Oracle procedure lets say:-
public class Employee{
String name;
Date birthDate;
int idNumber;
}
and I have a list looks like:-
ArrayList<Employee> alEmployees;
and I need to send the Employees list with more than one item to the stored procedure.
Can you please advise about the proper way to do it???
Thaaaaaaaaaaaaaaaaaaaanks,
March 09, 2011 - 9:23 am UTC
You would need to map that to a collection of objects.
probably the easiest way to accomplish that would be via JPublisher, it'll generate the code to facilitate mapping your Java data to SQL data.
Passing List of records to the Oracle Procedure
Mohammad, March 09, 2011 - 11:26 pm UTC
Hello Tom,
Firstly, I would like to thank you a lot for helping people.
I am tring to send list of objects to Oracle procedure lets say:-
public class Employee{
String name;
Date birthDate;
int idNumber;
}
and I have a list looks like:-
ArrayList<Employee> alEmployees;
and I need to send the Employees list with more than one item to the stored procedure.
Can you please advise about the proper way to do it???
Thaaaaaaaaaaaaaaaaaaaanks,
Followup March 9, 2011 - 9am Central time zone:
You would need to map that to a collection of objects.
probably the easiest way to accomplish that would be via JPublisher, it'll generate the code to facilitate mapping your Java data to SQL data.
-----------------------------------------------------
I would like to thank you a lot for fast responce, but still there is one question, I have no idea about the steps for this and I have no idea about the JPublisher...
Thaaaaaaaaaaaaaaaaaaanks
Passing array from Java to PLSQL
V.Hari, March 14, 2011 - 10:38 am UTC
Hi,
Thanks for your wonderful site and for your spelindid service to the oracle community.
If java as to send me an array of data like below, Need to know how should i declare the array in Oracle to make use of FORALL for bulk operations.
Empno, EmpName, Location, Deptno
101 Tom US D001
102 Rajini INDIA D002
103 Hari INDIA D003
Sample Code - Should i use SQL types like below or can use another form like Create or replace Type Record ?
Declaration Part in Oracle
CREATE OR REPLACE TYPE EMP_TYPE is object
(
empno Number(10),
empname varchar2(100),
Location varchar2(50),
dept varchar2(10)
);
CREATE OR REPLACE TYPE TY_EMP_TYPE IS TABLE OF EMP_TYPE;
Java Part
final ListlistOfEmployees = new LinkedList();
Employee e1 = new Employee();
e.setEmpId(101);
e.setEmpName("TOM");
e.setLocation("US");
e.Deptno("D001");
listOfEmployees.add(e1);
Employee e2 = new Employee();
e.setEmpId(102);
e.setEmpName("RAJINI");
e.setLocation("INDIA");
e.Deptno("D002");
listOfEmployees.add(e2);
// Like wise for rest of the data, add the data to the array.
// Now, create an array descriptor
ArrayDescriptor descriptor = ArrayDescriptor.createDescriptor( "TY_EMP_TYPE", dconn );
ARRAY array_to_pass = new ARRAY( descriptor, dconn, (Object[]) listOfEmployees.toArray());
ps = (OracleCallableStatement)dconn.prepareCall("begin insert_employees(:1); end;");
ps.setARRAY( 1, array_to_pass );
ps.execute();
conn.commit();
}
Basic logic is to get the data from the front end screen and java to pass the data to Oracle package. Using arrays for best performance.
Please let me know your views.
Thanks for your valuable time.
Regards
V.Hari
March 14, 2011 - 12:03 pm UTC
you cannot send/receive a plsql record type from any language other than plsql.
you can send/receive a collection of records to/from any language that can connect to and use Oracle.
Passing arrays to plsql
V.Hariharaputhran, March 14, 2011 - 12:37 pm UTC
Mr.Oracle
Thanks for your time.
Inshort
for the below data set from java, please help
Empno, EmpName, Location, Deptno
101 Tom US D001
102 Rajini INDIA D002
103 Hari INDIA D003
Is the below declaration correctCREATE OR REPLACE TYPE EMP_TYPE is object
(
empno Number(10),
empname varchar2(100),
Location varchar2(50),
dept varchar2(10)
);
CREATE OR REPLACE TYPE TY_EMP_TYPE IS TABLE OF EMP_TYPE;
PROCEDURE PR_INSERT(p_emparray in TY_EMP_TYPE)
Regards
V.Hari
March 14, 2011 - 12:43 pm UTC
I cannot tell if your object is correct, it would fit the data displayed, but an example of data displayed does not specify all of the data values that could be used.
So, assuming you got the datatypes right - sure, the definitions look syntactically correct so far (but I'm not a compiler - for that you'd want to run the code :) )
Passing arrays to Oracle
V.Hariharaputhran, March 14, 2011 - 12:59 pm UTC
Mr.Oracle,
Thanks Guru. All i was looking is about the mapping and processing the java array in plsql.
Table
create table emp(Empno Number(10), EmpName Varchar2(100), Location Varchar2(50), Deptno Varchar2(10), Hiredate date);
Arrays Declaration
CREATE OR REPLACE TYPE EMP_TYPE is object
(
empno Number(10),
empname varchar2(100),
Location varchar2(50),
deptno varchar2(10),
hiredate date
);
CREATE OR REPLACE TYPE TY_EMP_TYPE IS TABLE OF EMP_TYPE;
PROCEDURE PR_INSERT(p_emparray in TY_EMP_TYPE)
Thanks for your time.
Regards
V.Hari
Invalid values of string array
Vladimir, March 28, 2011 - 1:52 am UTC
Thanks a lot for this discussion, it was very useful for me. But I still have an issue with array output parameter passing from oracle to java layer. Here is my reproduce script:
SQL script is:
create or replace type test_array as table of varchar2(100);
CREATE OR REPLACE PROCEDURE test_arrays_proc(NAMEARRAY OUT test_array)
AS
BEGIN
NAMEARRAY := test_array();
NAMEARRAY.EXTEND;
NAMEARRAY(NAMEARRAY.LAST) := 'test1';
NAMEARRAY.EXTEND;
NAMEARRAY(NAMEARRAY.LAST) := 'test2';
NAMEARRAY.EXTEND;
NAMEARRAY(NAMEARRAY.LAST) := 'test3';
END;
Java:
package knock;
import java.sql.Array;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Types;
import oracle.jdbc.pool.OracleDataSource;
public class OracleArrayTest {
private static void execTest(Connection conn) throws SQLException {
CallableStatement cs = conn.prepareCall("call test_arrays_proc(?)");
cs.registerOutParameter(1, Types.ARRAY, "TEST_ARRAY");
cs.execute();
Array namesArray = cs.getArray(1);
Object result = namesArray.getArray();
}
public static void main(String[] argv) {
try {
OracleDataSource ds = new oracle.jdbc.pool.OracleDataSource();
ds.setURL("jdbc:oracle:thin:@ora31:1521/FCSMDMD");
Connection conn = ds.getConnection("strategy", "strategy");
execTest(conn);
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
When you call test_arrays_proc, the value of NAMEARRAY out params will be: ["test1", "test2", "test3"]
But, when you execute the Java example, you will see, that result object will contain String[3]{"???", "???", "???"}
Driver version: ojdbc14_g-10.2.0.4.jar
Manifest:
Manifest-Version: 1.0
Specification-Title: Oracle JDBC driver classes for use with JDK14
Created-By: 1.4.2_14 (Sun Microsystems Inc.)
Implementation-Title: ojdbc14_g.jar
Specification-Vendor: Oracle Corporation
Specification-Version: Oracle JDBC Driver version - "10.2.0.4.0"
Implementation-Version: Oracle JDBC Driver version - "10.2.0.4.0"
Implementation-Vendor: Oracle Corporation
Implementation-Time: Sat Feb 2 11:53:00 2008
March 29, 2011 - 2:59 am UTC
reading this code, I see it would produce:
<nothing>
where is the bit of code that shows it prints the wrong stuff?
Invalid values of string array
Vladimir, March 29, 2011 - 10:18 pm UTC
Sorry, about previous useless post. Here is the printing example:
package knock;
import java.io.IOException;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Types;
import oracle.sql.ARRAY;
import oracle.sql.CHAR;
import oracle.sql.Datum;
import oracle.jdbc.driver.OracleConnection;
import oracle.jdbc.pool.OracleDataSource;
public class OracleArrayTest {
private static void execTest(Connection conn) throws SQLException, IOException {
CallableStatement cs = conn.prepareCall("call test_arrays_proc(?)");
cs.registerOutParameter(1, Types.ARRAY, "TEST_ARRAY");
cs.execute();
ARRAY namesArray = (ARRAY) cs.getArray(1);
Datum [] oraArr = namesArray.getOracleArray();
for (int i = 0; i < oraArr.length; ++i) {
CHAR c = (CHAR) oraArr[i];
String s = c.toString();
System.out.println("The resulting CHAR[" + i + "] charset = " + c.getCharacterSet() + " and value = \"" + s + "\" and expected value is \"" + new String(c.getBytes(), "windows-1251") + "\"");
}
}
public static void main(String[] argv) {
try {
OracleDataSource ds = new oracle.jdbc.pool.OracleDataSource();
ds.setURL("jdbc:oracle:thin:@ora31:1521/FCSMDMD");
Connection conn = ds.getConnection("strategy", "strategy");
short oracleId = ((OracleConnection)conn).getJdbcCsId();
System.out.println("Connection charset id: " + oracleId + " (which equals UTF8_CHARSET)");
execTest(conn);
conn.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
Output is:
Connection charset id: 871 (which equals UTF8_CHARSET)
The resulting CHAR[0] charset = CL8MSWIN1251 and value = "???" and expected value is "test1"
The resulting CHAR[1] charset = CL8MSWIN1251 and value = "???" and expected value is "test2"
The resulting CHAR[2] charset = CL8MSWIN1251 and value = "???" and expected value is "test3"
Passing array to Java
R.Zorge, October 08, 2013 - 11:35 pm UTC
How about passing array from PL/SQL to Java. Provided we have all the necessary JDBC libraries.
Is it possible for Java stored proc connect to SQL Server, execute query based on the input parameters stored in local Oracle look-up table and then insert result-set of that query back into Oracle but different table. Sort of extract/load round-trip without the transformation.
We can't use Transparent Gateway. Some primitive example would be very helpful.
Thank you in advance.
October 09, 2013 - 5:57 pm UTC
passing an array from java to plsql:
http://asktom.oracle.com/pls/asktom/f?p=100:11:::::P11_QUESTION_ID:712625135727 getting a java stored procedure to connect to sql server would involve loading the jdbc thin driver for sql server into the Oracle database and then opening a new connection in the stored procedure.
I don't know why you cannot use the heterogeneous gateway - it comes with the database and would let you just use sql. It is not that you CANNOT use the gateway, it is that you are making a decision NOT TO use the gateway. You certainly *can* use the gateway, you are choosing not to.
sorry, I don't have any examples of loading the sql server jdbc drivers - I don't have sql server installed anywhere (surprisingly enough..)
Invalid values in array
A reader, December 10, 2021 - 2:26 pm UTC
Did we receive any answeror solution to the already asked question, that is receiving output value as ??? In the array of object after store proc call
December 10, 2021 - 4:23 pm UTC
What exactly is the issue you're having? If you've got an issue, it's better to post a new question with a complete reproducible example