18

In SQL Server, you can do things like this:

INSERT INTO some_table (...) OUTPUT INSERTED.*
VALUES (...)

So that you can insert arbitrary sets of columns/values and get those results back. Is there any way to do this in Oracle?

The best I can come up with is this:

INSERT INTO some_table (...)
VALUES (...)
RETURNING ROWID INTO :out_rowid

...using :out_rowid as a bind variable. And then using a second query like this:

SELECT *
FROM some_table
WHERE ROWID = :rowid

...but this isn't quite the same as it returns everything within the column, not just the columns I inserted.

Is there any better way to do this without using a lot of PL/SQL and preferably with only one query?

Jason Baker
  • 192,085
  • 135
  • 376
  • 510
  • 1
    If it's the columns you're interested in (not the row data)... - How are you deriving the (...)? Surely at that point you know which columns are being referenced in the insert? – Jeffrey Kemp Jul 03 '09 at 05:27
  • I just read up on OUTPUT INSERTED (http://msdn.microsoft.com/en-us/library/ms177564.aspx). Apparently it allows you to pick whether the row data returned is that before or after any table triggers have run. Oracle's RETURNING clause doesn't support this - it only gives you the data after triggers have had a chance to change it. – Jeffrey Kemp Jul 03 '09 at 05:30
  • @ Jeffrey Kemp - I would know what those columns are. However, so should the database. :-) – Jason Baker Jul 04 '09 at 20:59

2 Answers2

6

Maybe I don't understand the question, but wouldn't this do it? (you must know what you want back)

INSERT INTO some_table (...)
VALUES (...)
RETURNING some_column_a, some_column_b, some_column_c,  ...  INTO :out_a, :out_b, :out_c, ...

@Vincent returning bulk collect into for multi-row insert works only in conjunction with forall (in another words if you insert from collection you can retrieve "results" into another)

Michal Pravda
  • 809
  • 4
  • 9
3

The RETURNING clause supports the BULK COLLECT INTO synthax. Consider (10g):

SQL> CREATE TABLE t (ID NUMBER);

Table created
SQL> INSERT INTO t (SELECT ROWNUM FROM dual CONNECT BY LEVEL <= 5);

5 rows inserted
SQL> DECLARE
  2     TYPE tab_rowid IS TABLE OF ROWID;
  3     l_r tab_rowid;
  4  BEGIN
  5     UPDATE t SET ID = ID * 2
  6      RETURNING ROWID BULK COLLECT INTO l_r;
  7     FOR i IN 1 .. l_r.count LOOP
  8        dbms_output.put_line(l_r(i));
  9     END LOOP;
 10  END;
 11  /

AADcriAALAAAAdgAAA
AADcriAALAAAAdgAAB
AADcriAALAAAAdgAAC
AADcriAALAAAAdgAAD
AADcriAALAAAAdgAAE

It works with multi-row UPDATE and DELETE with my version (10.2.0.3.0) but NOT with INSERT:

SQL> DECLARE
  2     TYPE tab_rowid IS TABLE OF ROWID;
  3     l_r tab_rowid;
  4  BEGIN
  5     INSERT INTO t (SELECT ROWNUM FROM dual CONNECT BY LEVEL <= 5)
  6      RETURNING ROWID BULK COLLECT INTO l_r;
  7     FOR i IN 1 .. l_r.count LOOP
  8        dbms_output.put_line(l_r(i));
  9     END LOOP;
 10  END;
 11  /

ORA-06550: line 7, column 5:
PL/SQL: ORA-00933: SQL command not properly ended

Maybe you have a more recent version (11g?) and the BULK COLLECT INTO is supported for multi-row INSERTs ?

Vincent Malgrat
  • 66,725
  • 9
  • 119
  • 171
  • I'm not so much worried about the number of rows as I am the number of columns. The number of rows will pretty much always be one while the columns will be variable. – Jason Baker Jul 02 '09 at 20:10
  • @Jason: I think you will have to use dbms_sql if the number of columns is variable/not known at compile time – Vincent Malgrat Jul 03 '09 at 07:59