Skip to Main Content

Breadcrumb

Question and Answer

Connor McDonald

Thanks for the question, Amin.

Asked: February 07, 2017 - 2:28 pm UTC

Last updated: February 07, 2017 - 6:01 pm UTC

Version: 12c

Viewed 1000+ times

You Asked

Hi Tom,
I have the following dynamic sql statement, I want to return the rowid of the inserted record into a variable but I get a command not properly ended error. What is the problem?


stmt:= 'INSERT INTO ' || destination_table_name || ' ( ' ||
col_list || ') (SELECT ' || col_list || ' FROM ' || interim_table_name ||
' where rownum =1) returning rowid into :1';

execute immediate stmt returning into destrowid;

and Connor said...

That's not a dynamic SQL issue...that is just a plain SQL issue. You cannot do returning with insert-select

SQL> create table t ( x int );

Table created.

SQL>
SQL> variable j number
SQL> insert into t
  2  select 1 from dual
  3  returning x into :j;
returning x into :j
          *
ERROR at line 3:
ORA-00933: SQL command not properly ended


SQL> insert into t values (1 )
  2  returning x into :j;

1 row created.



Also take a look here for options

http://docs.oracle.com/database/121/LNPLS/tuning.htm#BCGHDEJH

Rating

  (2 ratings)

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

Comments

A reader, February 08, 2017 - 6:02 am UTC

Thank you for you answer.

But I still have a problem. I get the table name as a parameter and I can't declare a record variable using %rowtype and because of this I have to generate a column list and an Insert Select query. At the same time I want to return the rowid after insert. How can I do this considering the dynamic table name?

on Dynamic inserts

Rajeshwaran, Jeyabal, February 08, 2017 - 8:35 am UTC

....
I get the table name as a parameter and I can't declare a record variable using %rowtype and because of this 
I have to generate a column list and an Insert Select query. At the same time I want to return the rowid after insert.
How can I do this considering the dynamic table name
....


Still don't understand the need for ROWID here, as pointed by Connor on the above link, RETURNING clause is only possible on insert ...values(...) statement and not with INSERT ...SUB_QUERY.

For Dynamic insertion, you could rely on DBMS_SQL API.

demo@ORA11G> create or replace procedure load_data(
  2     p_source varchar2,
  3     p_destination varchar2 )
  4  as
  5     l_sql long;
  6     l_cursor int;
  7     l_source varchar2(30);
  8     l_destination varchar2(30);
  9     l_col_cnt int;
 10     l_desc_t dbms_sql.desc_tab;
 11     l_source_collist long;
 12     l_dest_collist long;
 13     l_rows int;
 14  begin
 15     l_source := dbms_assert.sql_object_name(p_source);
 16     l_destination := dbms_assert.sql_object_name(p_destination);
 17
 18     l_cursor := dbms_sql.open_cursor;
 19     dbms_sql.parse(l_cursor,'select * from '||l_source,dbms_sql.native);
 20     dbms_sql.describe_columns(l_cursor,l_col_cnt,l_desc_t);
 21     for i in 1..l_col_cnt
 22     loop
 23             l_source_collist := l_source_collist ||l_desc_t(i).col_name||',';
 24     end loop;
 25     l_source_collist := trim(',' from l_source_collist);
 26     dbms_sql.close_cursor(l_cursor);
 27
 28     l_cursor := dbms_sql.open_cursor;
 29     dbms_sql.parse(l_cursor,'select * from '||l_destination,dbms_sql.native);
 30     dbms_sql.describe_columns(l_cursor,l_col_cnt,l_desc_t);
 31     for i in 1..l_col_cnt
 32     loop
 33             l_dest_collist := l_dest_collist ||l_desc_t(i).col_name||',';
 34     end loop;
 35     l_dest_collist := trim(',' from l_dest_collist);
 36     dbms_sql.close_cursor(l_cursor);
 37
 38     l_sql := ' insert into '||l_destination||' ( '||l_dest_collist ||' ) '||
 39                  ' select '||l_source_collist||' from '||l_source ;
 40
 41     l_cursor := dbms_sql.open_cursor;
 42     dbms_sql.parse(l_cursor,l_sql,dbms_sql.native);
 43     l_rows := dbms_sql.execute(l_cursor);
 44     dbms_sql.close_cursor(l_cursor);
 45     dbms_output.put_line('Row count ='||l_rows);
 46  end;
 47  /

Procedure created.

demo@ORA11G> create table emp as select * from scott.emp;

Table created.

demo@ORA11G> create table emp_temp as select *
  2  from scott.emp
  3  where 1 = 0;

Table created.

demo@ORA11G> begin
  2     load_data(
  3             p_source=>'EMP',
  4             p_destination=>'EMP_TEMP');
  5  end;
  6  /
Row count =14

PL/SQL procedure successfully completed.

demo@ORA11G> select count(*) from emp_temp;

  COUNT(*)
----------
        14

demo@ORA11G>