Skip to Main Content
  • Questions
  • Inserting rows & getting the generated primary key in JDBC (in one transaction)

Breadcrumb

Question and Answer

Tom Kyte

Thanks for the question, Achille.

Asked: October 29, 2006 - 4:17 pm UTC

Last updated: October 29, 2006 - 5:56 pm UTC

Version: 10.2.0

Viewed 1000+ times

You Asked

Tom
I have a table with a auto-incrementing id. From time to time I want to insert rows to this table, but want to be able to know what the pk of the newly inserted row is. One way I could do this is:

SQL> variable var1 number;

SQL> insert into test (name) values ('test value') returning id into :var1;
1 row created.

SQL> print var1;
13

How can I now do the same thing in jdbc?

Just to give you an idea, here's what I've been trying to do: As best as I can write it, that in java should be:

String query = "insert into test (name) values ('test') returning id into :var1";
OracleCallableStatement cs = (OracleCallableStatement) conn.prepareCall(query);
cs.registerOutParameter(1, OracleTypes.NUMBER );
cs.execute();
System.out.println(cs.getInt(1));

The problem is that when I run it, I get an error: java.sql.SQLException: Protocol violation

Another thing I've tried is doing the same thing but in a procedure:
ie: declare pk number; begin execute immediate 'insert into test (name) values (''test'') returning id into :var1' using out pk; end;

No dice in that either.

Now I know I could do this in two transactions: first a select for the sequence.nextval then I can manually use that sequence as the primary key (and thus removing the trigger alltogether )

Something else I could do is simply wrap the whole thing in a stored procedure and then call the procedure... but that might end up being too much work to maintain (Ie changing a methdo would require me to edit the code and also the stored procedure)

I've seen in the forums people have been able to do this in ONE transaction in .net. Why Can't I do it JDBC?

Thanks, Achille



and Tom said...

you'll want to use a plsql block:

begin
insert into t ... returning into :x;
end;


and prepare that as a callable statement and bind :X as an OUT parameter. Plsql can do the old "in out"

Rating

  (4 ratings)

Is this answer out of date? If it is, please let us know via a Comment

Comments

Thanks, tom

Achille, October 29, 2006 - 7:40 pm UTC

Simple, elegant, and flawless -- Thanks again!

A question on that

A reader, October 29, 2006 - 8:44 pm UTC

Does that allow for one to bind incoming AND outgoing parameters at the same time?

I was unable to do them both, ie something like this:

String query = "begin insert into test (name) values (?) returning id into :x; end;";

OracleCallableStatement cs = (OracleCallableStatement) conn.prepareCall(query);

cs.registerOutParameter(2, OracleTypes.NUMBER );

cs.setString(1,"test entry");

That seems to fail no matter what parmeters I place.

10.2 JDBC drivers support DML returning

laatikko, October 30, 2006 - 4:23 am UTC

Oracle® Database JDBC Developer's Guide and Reference
10g Release 2 (10.2)

Chapter 5 "Oracle extensions"




Alberto Dell'Era, October 30, 2006 - 4:31 am UTC

laatikko beats me by the minute ;)

Direct link:

</code> http://download-uk.oracle.com/docs/cd/B19306_01/java.102/b14355/oraint.htm#sthref296 <code>

More to Explore

PL/SQL demos

Check out more PL/SQL tutorials on our LiveSQL tool.

PL/SQL docs

PL/SQL reference manual from the Oracle documentation library