Follow Us on Twitter

Solving ORA-22992 in one line of SQL (and a global temporary table)

by Martin Schapendonk on January 20, 2011 · 1 comment

Right now, I’m working on an application that migrates a lot of data between two Oracle schemas. Until now, these schemas lived in the same database. To support migrations between several testing environments (living on different databases) we thought it would be a good idea to migrate the data over a database link (the most compelling reason to do so was to reduce configuration management work as we would have only one schema of source data and migration software to maintain). And so we did.

The code initially looked like this:

create table clob_table (
  id number
, name varchar2(100)
, contents clob
);

declare
  r_clob clob_table%rowtype;
begin
  r_clob.name := 'Testing';
  r_clob.contents := ''; -- fill it with a clob
  insert into clob_table values r_clob;
end;
/

Please note that we don’t fill the ID column, as it is filled by a trigger on clob_table. As soon as clob_table lives in another database, we encountered ORA-22992, “cannot use LOB locators selected from remote tables”. Damn, that might spoil the whole party!

The Oracle documentation states that you can only use LOBs across database links as long as it is the only column in the DML-statement, or you use inserts of the form “insert into … select … from …”.

Our first idea was to use a RETURNING clause on the statement and update the CLOB value afterwards with a separate UPDATE statement. Unfortunately, RETURNING is also not supported across database links (ORA-22816: unsupported feature with RETURNING clause). To get that working, we would need even more code to retrieve the ID (making the trigger useless). Because we also didn’t know how an INSERT plus an UPDATE across a database link might hurt performance (instead of just an INSERT), we decided to abandon this route.

While thinking about the other supported form (“insert into … select … from …”) we finally arrived at a solution we’re quite happy with. First we created a global temporary table:

create global temporary table tmp_clob_table as
  select *
  from clob_table
  where 1=0
;

Secondly, we modified our code to first insert into this temporary table, then insert into the remote table:

declare
  r_clob clob_table%rowtype;
begin
  r_clob.name := 'Testing';
  r_clob.contents := ''; -- fill it with a clob
  insert into tmp_clob_table values r_clob;
  insert into clob_table select * from tmp_clob_table;
end;
/

Right now, we are quite happy with this solution. It had almost no performance impact and it doesn’t clutter up the code.

Solving ORA-22992 in one line of SQL (and a global temporary table), 3.7 out of 5 based on 3 ratings
Ratings:
VN:D [1.9.22_1171]
Rating: 3.7/5 (3 votes cast)

{ 1 comment… read it below or add one }

venkatesh May 31, 2017 at 9:00 pm

this code i tried to execute in remote database, doesn’t work.

Reply

Leave a Comment

 

Previous post:

Next post:

About Whitehorses
Company profile
Services
Technology

Whitehorses website

Home page
Whitebooks
Jobs

Follow us
Blog post RSS
Comment RSS
Twitter