Skip to Main Content

Breadcrumb

Question and Answer

Tom Kyte

Thanks for the question, Jigish.

Asked: January 05, 2009 - 2:21 pm UTC

Last updated: January 06, 2009 - 10:25 am UTC

Version: 9.2.0

Viewed 10K+ times! This question is

You Asked

Hi Tom,

I am generating a lot of Insert statements from a source database, which will be executed in Destination database. I am using PL/SQL code to print Insert statements using DBMS_OUTPUT.PUT_LINE from few tables. So because of Max limit, after 250 characters I have to print the rest of the statement in new line. When the statement is printed like below:

INSERT INTO INSTRUMENT VALUES ('095000294E',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'','',NULL,'','','','',NULL,NULL,NULL,'TMP','','','095000294F','','','','','','','','095000022U','','ADV','','','','','CB1','N',NULL,'','',NULL,NU
LL,NULL,'',NULL,NULL,'','',NULL,'O',NULL,'','','','','','','','','','');

it gives this error:
LL,NULL,'',NULL,NULL,'','',NULL,'O',NULL,'','','','','','','','','','')
*
ERROR at line 2:
ORA-00917: missing comma

I tried continuation character(-), like below, but it does not work here.
'095000022U','','ADV','','','','','CB1','N',NULL,'','',NULL,NU-
LL,NULL,'',NULL,NULL,'','',NULL,'O',NULL,'','','','','','','','','','');

Can you please tell me, How can I continue a line here?
Appreciate your help.

and Tom said...

suggestion:

well, my first suggestion is "do not do this", but if you must - just build the inserts like this:

insert into t values (
'column1',
'column2',
'column3',
null,
null,
'whatever'
);


that way - you will be limited to dumping columns of length 250 or less and won't have to worry about any word wrapping issues - just use a separate dbms_output.put_line for each column...


Rating

  (3 ratings)

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

Comments

Brett, January 05, 2009 - 4:11 pm UTC

I agree with Tom that this is probably a bad idea, but then I've had to do this before since others said it must be done. I accomplished what you are looking for by loading the entire sql stmt into a variable and then looping through chopping as big of chunks as I could, but still paying attention to the comma delimiter. There are all kinds of pitfalls with this (which you will probably find and have to code around), but this should get you started:
select SUBSTR('1,2,3,4,5,6,7,8,9,10,11,12',1,INSTR('1,2,3,4,5,6,7,8,9,10,11,12',',',-10,1)) from dual;
You will have to use variables to keep track of the last place you started to print from, but I'm sure the above statement will give you an idea.
Tom Kyte
January 05, 2009 - 4:36 pm UTC

since he is printing it out using dbms_output - just calling dbms_output.putline for each column is the path of least resistance.

my reason for generating Insert statement is faster transfer of data

Jigish Thakkar, January 06, 2009 - 8:17 am UTC

Thanks a lot Tom & Brett, Your answers have helped me a lot. I used Tom's approach & the INSTR as said by Brett.

I decided to generate the insert statements using dbms_output.put_line for faster transfer of data from Production.

Basically what I need is, a faster way to populate specific data from Production to other Databases. Transferring & using Dump takes a lot of time because of size, and we do not need all the data from Production. We need only some specific data from few tables, and in 9i there seems no way to export one Dump using different queries for different tables.

Can you please tell me if my approach is correct? Or there is any other Better/Easier way to transfer data faster from one database to another?? Appreciate your help.

I modified my code as below, which generates insert statements:

--------------------------------------------------------
DECLARE

CURSOR my_cursor IS SELECT * FROM TEMPLATE WHERE EXISTS (SELECT UOID FROM INSTRUMENT WHERE UOID=TEMPLATE.C_INSTRUMENT);

rec_count number := 0;
I NUMBER := 1;
colon_position NUMBER;
to_position NUMBER := 1;
instr_position NUMBER := 1;
loop_thru NUMBER;
RESULTS VARCHAR2(4000);

BEGIN

dbms_output.enable(buffer_size => 1000000);

FOR my_rec IN my_cursor
LOOP

I := 1;
to_position := 1;
instr_position := 1;

-- Result which will be printed 250 characters per line (which is max limit of DBMS_OUTPUT.PUT_LINE)
RESULTS := 'INSERT INTO TEMPLATE VALUES ('''||my_rec.uoid||''','''|| my_rec.description||''','''|| my_rec.name||''','''||my_rec.a_product||''','''||my_rec.a_product_type||''','''|| my_rec.c_instrument||''','''||my_rec.a_client_bank||''','''|| my_rec.a_oper_bk_org||''');';

-- The below 2 replace statements put NULL value between two semicolons (,,)
-- whenever a Numeric column's value is NULL, it does not display anything for that, so the statement fails
-- It is required to put NULL or ''(double quotes) to identify NULL values, below 2 statements are solution for that
RESULTS := REPLACE (RESULTS,',,',',NULL,');
RESULTS := REPLACE (RESULTS,',,',',NULL,');

loop_thru := INSTR(RESULTS,',',-1,1);
colon_position := INSTR(RESULTS,',',instr_position,1);
to_position := colon_position;

--Printing Result
WHILE instr_position <= loop_thru LOOP
--DBMS_OUTPUT.PUT_LINE('I- '||I);
--DBMS_OUTPUT.PUT_LINE('instr_position- '||instr_position);
--DBMS_OUTPUT.PUT_LINE('colon_position- '||colon_position);
--DBMS_OUTPUT.PUT_LINE('to_position- '||to_position);

DBMS_OUTPUT.PUT_LINE(SUBSTR(RESULTS, I, to_position));

I := (1 + colon_position);
instr_position := (1 + colon_position);
colon_position := INSTR(RESULTS,',',instr_position,1);
to_position := ((colon_position-I)+1);
END LOOP;

-- This additional line is to Print the last remaining statement
DBMS_OUTPUT.PUT_LINE(SUBSTR(RESULTS, I));

rec_count := rec_count + 1;

END LOOP;

END;
/
-------------------------------------------------------
Tom Kyte
January 06, 2009 - 10:25 am UTC

... and in 9i there seems no way to export one
Dump using different queries for different tables.
...

so? just create a dmp file per table - put it into a script.


or better yet, just use a database link.

Name columns in INSERT that have not null values

Henry Stinson, August 15, 2012 - 4:40 pm UTC

One way to shorten the INSERT SQL command, in this case, where there are NULL values for a lot of columns, is to name the columns in the INSERT statement that have non-NULL values to be inserted and let the column default to NULL (assuming column is not defined with a non-NULL default value). If the INSERT statement is pretty much the same non-null columns all the time, that is easy to do, but if the number of non-null columns varies, then you'll have to write some code to format the SQL INSERT command.

More to Explore

DBMS_OUTPUT

More on PL/SQL routine DBMS_OUTPUT here