Robert Boyle, July 11, 2002 - 6:30 am UTC
Tom, sorry for posting here, but this should be a simple follow on from this question.
Can you not use the RETURNING clause in the insert of this example to retrieve the sequence number? In other words, are you restricted to only getting the sequence number by select the sequence.nextval before you do the insert?
Thanks
Robert
July 11, 2002 - 7:36 am UTC
sure, in fact, they do not even need to get the sequence technically, just the blob.
They could have used returning on the blob column as well.
Robert, July 11, 2002 - 9:38 am UTC
Tom,
Can you give an example of this?
We tried this in our code before without much luck.(SQLJ) We even tried running it as an anonymous plsql block but still no luck. We never received an error, and the row inserted ok, but we were never successful in returning the sequence id (which we need to update the blob later on in the code - although according to your statement we wouldn't need that..would the blob indicator do the job?).
Sorry for the follow up, but being having a limited knowledge of Java I am trying to put what I know from PLSQL into practise in SQLJ and I know it doesn't always work.
Cheers
R.
July 12, 2002 - 7:38 am UTC
Sure, in SQLJ, it would look like this:
ops$tkyte@ORA817DEV.US.ORACLE.COM> create table t ( x int );
Table created.
ops$tkyte@ORA817DEV.US.ORACLE.COM> create sequence t_seq;
Sequence created.
ops$tkyte@ORA817DEV.US.ORACLE.COM>
ops$tkyte@ORA817DEV.US.ORACLE.COM>
ops$tkyte@ORA817DEV.US.ORACLE.COM>
ops$tkyte@ORA817DEV.US.ORACLE.COM> create or replace
2 and compile java source named "returningTest"
3 as
4 import java.io.*;
5 import java.sql.*;
6
7 public class returningTest
8 {
9 public static void run() throws SQLException
10 {
11 int id = 0;
12
13 #sql { begin
14 insert into t values ( t_seq.nextval ) returning x into :out id;
15 end;
16 };
17
18 System.out.println( "java says " + id );
19 }
20
21 }
22 /
Java created.
ops$tkyte@ORA817DEV.US.ORACLE.COM> show errors
No errors.
ops$tkyte@ORA817DEV.US.ORACLE.COM>
ops$tkyte@ORA817DEV.US.ORACLE.COM>
ops$tkyte@ORA817DEV.US.ORACLE.COM> create or replace procedure returningTest
2 as language java
3 name 'returningTest.run()';
4 /
Procedure created.
ops$tkyte@ORA817DEV.US.ORACLE.COM>
ops$tkyte@ORA817DEV.US.ORACLE.COM> set serveroutput on
ops$tkyte@ORA817DEV.US.ORACLE.COM> exec dbms_java.set_output(100000)
PL/SQL procedure successfully completed.
ops$tkyte@ORA817DEV.US.ORACLE.COM> exec returningTest;
java says 1
PL/SQL procedure successfully completed.
ops$tkyte@ORA817DEV.US.ORACLE.COM> exec returningTest;
java says 2
PL/SQL procedure successfully completed.
Do you have example for jdbc?
Winston, April 17, 2003 - 9:28 pm UTC
Hi Tom,
Is there any way to directly retrieve the value from returning clause in java withou putting the "insert into ... returning" into a stored function? I tried something like this:
PreparedStatement ps = conn.prepareStatement( " insert into ttt values (tmp_seq.nextval) returning c1 into ? ");
ps.executeQuery();
rs = ps.getResultSet();
while (rs.next()) {
rs.getInt(1);
}
but I got "java.sql.SQLException: ORA-01008: not all variables bound
"
April 18, 2003 - 10:43 am UTC
conn.prepareStatement( "begin insert into
ttt values (tmp_seq.nextval) returning c1 into ?; end;");
will do that.
have to use callableStatement
winston, April 21, 2003 - 1:51 pm UTC
CallableStatement cs =
conn.prepareCall(
"begin insert into ttt values (tmp_seq.nextval) returning c1 into ?; end;");
int obj = 0;
cs.registerOutParameter(1, OracleTypes.INTEGER);
cs.execute();
obj = cs.getInt(1);
And I have benchmarked "returning clause" vs. 'insert + select seq from dual'. Using "returning clause" is Much faster and more scalable
missing JDBC method implementation ...
Klaus, September 08, 2003 - 10:33 am UTC
Hi all,
some questions about this topic, because the provided implementation is a bit tricky and not really obvious!
Why for example is the JDBC Standards defined method getGeneratedKeys not implemented for such purposes?(returning drawn Sequences-Id's while executing an Insert-Statement)
public ResultSet getGeneratedKeys() returns with a SQLException mentioning something like "feature not implemented!"
Why do we have to use an anonymous PL/SQL-Block, when
the SQL i'm executing is not PL/SQL-Block?
any ideas for future developments/corrections of the issue?
any comments/hints/etc are truly welcome!
kind regards
K:) UNGER
September 08, 2003 - 12:37 pm UTC
sorry, not really a java programmer -- I'm a database developer.
but -- we (oracle) don't have "generated keys" -- YOU (the developer) populated these keys explicitly. we cannot implement that which does not exist.
Another layer
George, December 10, 2003 - 11:01 am UTC
Suppose that you had a java program that called a stored procedure that contained an insert that you wanted to return the sequence num. to the java program (using the returning clause)
eg:
java calls the procedure
the procedure contains an insert that uses a sequence in the values clause, the java program needs that sequence number for future updates. What would the code look like for that?
Thanks for everything Tom, you're the man
December 10, 2003 - 3:47 pm UTC
java would prepare a callable statement:
begin p( ...., ? ); end;
where that last ? is the sequence as an out parameter and the ... are the rest of the inputs to the procedure to insert.
procedure would be:
procedure p( ....., p_seq OUT number )
is
begin
insert into t ( .... ) values ( .... ) returning ID into p_seq;
end;
Thanks!
George, December 10, 2003 - 4:47 pm UTC
blob insert examples in oracle provided examples
bob, May 06, 2004 - 9:28 am UTC
Tom,
LOB/jdbc docs specifically say that insert empty_blob(), followed by selecting for update the lob locator is the incorrect way to do it, that you should use "insert ... returning lob into ?" However, all the examples on otn and even the jdbc doc examples that I saw show the exact opposite approach. (insert followed by select for update)
I can't find the oracle doc I was reading that included two paragraphs highlighting the sequence of steps for inserting a blob the correct and incorrect way anymore, but shouldn't something like this work:
OracleCallableStatement cs =
conn.prepareCall(
"begin insert into table values (empty_blob()) returning theBlob into ?; end;"
);
cs.registerOutParameter(1, OracleTypes.BLOB);
ocs.execute();
oracle.sql.BLOB blob = ocs.getBLOB(1);
...usual jdbc blob loading stuff....
The doc mentioned that returning the lob locator made the "select for update" unnecessary.
May 06, 2004 - 9:33 am UTC
it is more efficient (less round trips) to insert/return
Yes, you can do the above (make sure to set that stupid "autocommit" 'feature' of jdbc OFF or it won't work.
You never needed the select for update if you just did the insert (you already have the row locked). You need the select for update whenever you retrieve the lob later in life (when you don't have the row locked) in order to modify it.
Inserting large blob through stored procedure interface
Tom, July 04, 2006 - 2:00 pm UTC
Hi Tom,
I'm in the middle of writing a piece of functionality which uses java to insert large binary documents into the database and I've hit a bit of a snag. I was happily following best practices and creating a stored procedure layer to encapsulate each of my logical transactions when I found nested deep within the jdbc developer's guide
<quote>
If you pass a BLOB to a PL/SQL procedure, the BLOB must be no bigger than 32K - 7. If you pass a BLOB that exceeds this limit, you will receive a SQLException.
</quote>
Given this, what would be your recommended approach to updating a blob column in the database?
I thought about writing the blob to a temp table then calling the stored procedure, but will this not lead to the [large] document being written to disk twice?
Equally, I considered inserting an empty blob and returning a blob handle from the stored procedure but I assume this would require me to grant insert and update on the table the blob is being inserted into rather than just granting execute on the package.
Is there any way to maintain the nice security layer a plsql interface provides and still have java insert blobs more than 32k?
July 07, 2006 - 9:12 pm UTC
have the blob return the newly created lob locator to the java program and let it "stream" the data in using whatever size it wants.
eg: java does not try to pass 2gig of data to Oracle, java calls the procedure and gets a "stream" - much like a file handle, well exactly like one - and "writes the data" to the stream.
or, if the security implications (need update on the COLUMN of that TABLE - grant update (column) on t to java_id;) don't work for you - you can provide you own "streaming" API - where the java app sends you up to 32k at a time plus the lob locator to write to.