Skip to Main Content

Breadcrumb

Question and Answer

Tom Kyte

Thanks for the question, Carolyn.

Asked: August 28, 2000 - 11:32 am UTC

Last updated: May 28, 2009 - 5:32 pm UTC

Version: Oracle 8.0.5

Viewed 1000+ times

You Asked

Tom-

I've coded a procedure to export information from the Oracle Database to a text file using PL/SQL. It is necessary to Pad all the variables (LPAD Numbers with zeros, RPAD varchars with spaces) for the Mainframe system to read them accurately.

Everything works great except I'm getting the following error when I attempt to pad a LONG:
DECLARE
*
ERROR at line 1:
ORA-06510: PL/SQL: unhandled user-defined exception
ORA-06512: at "SYS.UTL_FILE", line 103
ORA-06512: at "SYS.UTL_FILE", line 222
ORA-06512: at line 311

I've attempted to throw the LONG into a CHAR thinking you just can't pad a long, but it does not PAD more than 400 spaces.

Can you help?
I'm new to this.
Thanks,
Carrie

and Tom said...

I think, based on the line numbers in the stack trace, this is due to your linesize exceeding the default limit of 1022 bytes/line. When you fopen the file -- you can specify a maxlinesize upto 32k. The default is 1022.

Here is an example showing this and how to solve it. It takes any query and dumps it to a fixed length file based on the data dictionary lengths....

tkyte@ORA806.WORLD> create or replace
2 function dump_csv( p_query in varchar2,
3 p_dir in varchar2 ,
4 p_filename in varchar2,
5 p_max_linesize in number default 32000 )
6 return number
7 is
8 l_output utl_file.file_type;
9 l_theCursor integer default dbms_sql.open_cursor;
10 l_columnValue varchar2(4000);
11 l_status integer;
12 l_colCnt number default 0;
13 l_cnt number default 0;
14 l_line long;
15 l_descTbl dbms_sql.desc_tab;
16 begin
17 l_output := utl_file.fopen( p_dir, p_filename,
18 'w', p_max_linesize );
19
20 dbms_sql.parse( l_theCursor, p_query,
dbms_sql.native );
21 dbms_sql.describe_columns( l_theCursor,
22 l_colCnt, l_descTbl );
23
24 for i in 1 .. l_colCnt loop
25 dbms_sql.define_column( l_theCursor, i,
26 l_columnValue, 4000 );
27
28 if ( l_descTbl(i).col_type = 2 ) /* number type */
29 then
30 L_descTbl(i).col_max_len :=
31 l_descTbl(i).col_precision+2;
32 elsif ( l_descTbl(i).col_type = 12 ) /* date type */
33 then
34 /* length of my date format */
35 l_descTbl(i).col_max_len := 20;
36 elsif ( l_descTbl(i).col_Type = 8 ) /* LONG type */
37 then
38 l_descTbl(i).col_max_len := 2000;
39 end if;
40 end loop;
41
42 l_status := dbms_sql.execute(l_theCursor);
43
44 loop
45 exit when ( dbms_sql.fetch_rows(l_theCursor) <= 0 );
46 l_line := null;
47 for i in 1 .. l_colCnt loop
48 dbms_sql.column_value( l_theCursor, i,
49 l_columnValue );
50 l_line := l_line ||
rpad( nvl(l_columnValue,' '),
51 l_descTbl(i).col_max_len );
52 end loop;
53 utl_file.put_line( l_output, l_line );
54 l_cnt := l_cnt+1;
55 end loop;
56 dbms_sql.close_cursor(l_theCursor);
57 utl_file.fclose( l_output );
58 return l_cnt;
59 end dump_csv;
60 /

Function created.

tkyte@ORA806.WORLD>
tkyte@ORA806.WORLD> declare
2 l_rows number;
3 begin
4 l_rows := dump_csv( 'select * from user_views' ,
5 '/tmp',
6 'test.dat',
7 1022 );
8 end;
9 /
declare
*
ERROR at line 1:
ORA-06510: PL/SQL: unhandled user-defined exception
ORA-06512: at "SYS.UTL_FILE", line 103
ORA-06512: at "SYS.UTL_FILE", line 306
ORA-06512: at "TKYTE.DUMP_CSV", line 52
ORA-06512: at line 4


tkyte@ORA806.WORLD>
tkyte@ORA806.WORLD> declare
2 l_rows number;
3 begin
4 l_rows := dump_csv( 'select * from user_views' ,
5 '/tmp',
6 'test.dat' );
7 dbms_output.put_line( to_char(l_rows) ||
8 ' rows extracted to ascii file' );
9 end;
10 /
1 rows extracted to ascii file

PL/SQL procedure successfully completed.


Rating

  (32 ratings)

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

Comments

Error

jimmy, June 27, 2002 - 5:31 am UTC

I am getting error
ORA-06510: PL/SQL: unhandled user-defined exception
ORA-06512: at "SYS.UTL_FILE", line 98
ORA-06512: at "SYS.UTL_FILE", line 157
ORA-06512: at "MSSL.F_USEP_CSV", line 13
ORA-06512: at line 4

The line 4, 13 declares and use utl_file.

Tom Kyte
June 27, 2002 - 8:32 am UTC

did you set the utl_file_dir init.ora parameter. what is the exact code.

Export information from the Oracle Database to a text file using PL/SQL.

Nenu, September 23, 2002 - 6:04 pm UTC

I did try to the below function with p_max_linesize but i am still getting this error.

ERROR at line 1:
ORA-06510: PL/SQL: unhandled user-defined exception
ORA-06512: at "SYS.UTL_FILE", line 82
ORA-06512: at "SYS.UTL_FILE", line 120
ORA-06512: at "SURFPAC_DEV.DUMP_CSV", line 15
ORA-06512: at line 4

Any help would be greatly appriciated.
Thank Much.

Tom Kyte
September 24, 2002 - 7:29 am UTC

Yeah, the stack trace is totally different (error on line 15, NOT 311)

So, the fopen is failing -- I would hazzard a guess that you didn't set the UTL_FILE_DIR init.ora parameter properly (or at all)

Export information from the Oracle Database to a text file using PL/SQL.

nenu, September 24, 2002 - 4:02 pm UTC

Thanks. I had not set the parameter in the init.ora file.

I had a other question regarding this. I need to schedule a Job from the server, so that, it calls this function every month on the 7th day and dumps the query results in a specified directory.

I have little knowledge about this. Could you please suggest what i need to do. I am very new to all this.

Thanks Much.



Tom Kyte
September 24, 2002 - 4:07 pm UTC

You want to read up on DBMS_JOB, documentation is found in the supplied packages guide:

</code> http://docs.oracle.com/docs/cd/A87860_01/doc/appdev.817/a76936/dbms_job.htm#999107 <code>



You can

declare
l_job number;
begin
dbms_job.submit( l_job,
'your_stored_procedure;'
add_months(trunc(sysdate,'month'),1)+6,
'add_months(trunc(sysdate,''month''),1)+6' );
commit;
end;
/

(but make sure to set the relevant JOB_QUEUE_* init.ora parameters! so jobs run by themselves)


that'll run your procedure on the 7th day of every month at midnight.

Export information from the Oracle Database to a text file using PL/SQL.

nenu, September 25, 2002 - 1:18 pm UTC

I am a bit confused about the setting of the job.
I read we need to set the JOB_QUEUE_PROCESSES init parameter greater than 0 for the job to be run automatically. Is this the only parameter we set.

Function I call is the dump_csv function which you have described above to dump the Ascii file. Do I set the IN coming parameters in that function p_query, p_separator, p_dir, p_filename in the dbms_job.submit, when i call this function from there. The above parameters(dump_csv function ) are going to be same always. How do I execute the dbms_job.submit procedure.

Thanks for replying to all my questions.
Regards.

Tom Kyte
September 25, 2002 - 3:00 pm UTC

before 9i, you have job_queue_processes = N and N must be greater then zero for jobs to run by themselves.

you also have job_queue_interval = N and N is in seconds and defines how often the queue will be checked. 60 is typically a good number.


I thought I did show you how to call dbms_job:

declare
l_job number;
begin
dbms_job.submit( l_job,
'your_stored_procedure;'
add_months(trunc(sysdate,'month'),1)+6,
'add_months(trunc(sysdate,''month''),1)+6' );
commit;
end;
/

just change your_stored_procedure; to

'dump_csv( ''select ....'', ''/blah'', ''test.csv'' );'



Export information from the Oracle Database to a text file using PL/SQL.

nenu, September 25, 2002 - 5:24 pm UTC

I get the below error. Do i need to set a value for NO_PARSE in this procedure call.

Thanks for all the help!
Regards.

SQL>  declare
  2        l_job number;
  3     begin
  4       dbms_job.submit( l_job,
  5   'dump_csv( ''select * from    frms_bor_approps;'', ', ', ''/frmstest'', ''test007.txt'');',
  6             add_months(trunc(sysdate,'month'),1)+6,
  7            'add_months(trunc(sysdate,''month''),1)+6' );
  8         commit;
  9*    end;
 10  /
     dbms_job.submit( l_job,
     *
ERROR at line 4:
ORA-06550: line 4, column 6:
PLS-00306: wrong number or types of arguments in call to 'SUBMIT'
ORA-06550: line 4, column 6:
PL/SQL: Statement ignored
 

Tom Kyte
September 25, 2002 - 6:49 pm UTC

Ok, three things

1) you are missing a quote in there 
...approps;'', ', ', ''/frmstes...
...approps;'', '','', ''/frmstes      <<<-should be

2) no semi in the select:

...approps;'', '','', ''/frmstes    
...approps '', '','', ''/frmstes      <<<-should be

3) whoops, it is a function, so:


ops$tkyte@ORA920.US.ORACLE.COM> declare
  2        l_job number;
  3  begin
  4       dbms_job.submit( l_job,
  5             'declare
  6                 n int;
  7              begin
  8                  n := dump_csv( ''select * from    frms_bor_approps'',
  9                                 '','',
 10                                 ''/frmstest'',
 11                                 ''test007.txt'');
 12              end;',
 13             add_months(trunc(sysdate,'month'),1)+6,
 14            'add_months(trunc(sysdate,''month''),1)+6' );
 15         commit;
 16     end;
 17  /

PL/SQL procedure successfully completed.


works nicely.

 

Export information from the Oracle Database to a text file using PL/SQL.

Nenu, September 25, 2002 - 7:08 pm UTC

Thanks Tom, it worked perfect. Couldn't have done it without your help.

Regards.


Export information from the Oracle Database to a text file using PL/SQL.

nenu, September 26, 2002 - 11:45 am UTC

Hi Tom, I ran a test to see if it dump the file in the specified directory. But, i didn't see the dump file.
I ran a query on dba_jobs, it did show me the next_sec which changed after 2 mins when i ran the same query. So, that means the job did run. So, why don't i see the dump file in the specified directory.

Thanks Much.
Regards.

select JOB, LAST_DATE, NEXT_DATE, WHAT, THIS_SEC, NEXT_SEC, INTERVAL from dba_jobs;

declare
l_job number;
begin
dbms_job.submit( l_job,
'declare
n int;
begin
n := dump_csv( ''select sysdate from dual'',
'','',
''/frmstest'',
''test008.txt'');
end;',
sysdate + 2 / 1440,
'sysdate + 2 / 1440' );
commit;
end;
/


Tom Kyte
September 26, 2002 - 11:59 am UTC

how about failures? any failures?

whats in your alert log?

Export information from the Oracle Database to a text file using PL/SQL.

nenu, September 26, 2002 - 12:23 pm UTC

Tom, this is what is see in my alert log file.
Do you think p_separator is causing problem here. As we just have one field in the query,"sysdate".

Thanks Much.
Regards.

Thu Sep 26 08:36:16 2002
Errors in file D:\ORANT\RDBMS73\trace\frmsSNP0.TRC:
ORA-12012: error on auto execute of job 2
ORA-06510: PL/SQL: unhandled user-defined exception
ORA-06512: at "SYS.UTL_FILE", line 82
ORA-06512: at "SYS.UTL_FILE", line 120
ORA-06512: at "SURFPAC_DEV.DUMP_CSV", line 15
ORA-06512: at line 4

Thu Sep 26 08:39:16 2002
Errors in file D:\ORANT\RDBMS73\trace\frmsSNP0.TRC:
ORA-12012: error on auto execute of job 2
ORA-06510: PL/SQL: unhandled user-defined exception
ORA-06512: at "SYS.UTL_FILE", line 82
ORA-06512: at "SYS.UTL_FILE", line 120
ORA-06512: at "SURFPAC_DEV.DUMP_CSV", line 15
ORA-06512: at line 4

Tom Kyte
September 26, 2002 - 2:46 pm UTC

what is line 15 of your dump_csv.

If it is the fopen -- you forgot to set up utl_file_dir


Export information from the Oracle Database to a text file using PL/SQL.

nenu, September 26, 2002 - 3:35 pm UTC

Hi Tom, It creates a dump file through test procedure for function dump_csv. But, it doesn't create the dump file when i schedule it through DBMS_JOB.submit. 
I did create the util_file_dir init.ora parameter. Also, the job_queue_processes parameter is set to 1. Do, i need to increase that no. I am running this job from my machine and the "d:\frmstest" directory exist in the server machine. Should that make a difference. But, it creates a dump file from my machine when i run the test proc for dump_csv function.

Sorry, for asking so many questions.
Thanks for all the help.
Regards.

below are the line no.
SQL> 15
 15*    begin
SQL> 16
 16*        l_output := utl_file.fopen( p_dir, p_filename, 'w');

SQL> declare
  2          l_rows    number;
  3      begin
  4          l_rows := dump_csv( 'select FUND, TYPE from frmsfund_xref',
  5                              ',',
  6                              'd:\frmstest',
  7                              'test.dat' );
  8         dbms_output.put_line( to_char(l_rows) ||
  9                               ' rows extracted to ascii file' );
 10     end;
 11  /

PL/SQL procedure successfully completed..  

Tom Kyte
September 26, 2002 - 3:45 pm UTC

I do not understand something here.


What do you mean "i am running the job from my machine" (where is the job really running)?

and

"it created a sump file from my machine when ..." (where is that file created)?

you are using windows semantics above, but unix files below:

s$tkyte@ORA920.US.ORACLE.COM> declare
2 l_job number;
3 begin
4 dbms_job.submit( l_job,
5 'declare
6 n int;
7 begin
8 n := dump_csv( ''select * from frms_bor_approps'',
9 '','',
10 ''/frmstest'',
11 ''test007.txt'');
12 end;',
13 add_months(trunc(sysdate,'month'),1)+6,
14 'add_months(trunc(sysdate,''month''),1)+6' );
15 commit;
16 end;
17 /


I rather suspect the UNIX database where the job is running (different from the windows database you have been testing with) is NOT setup with utl_file_dir properly.


Run your tests on the database where the JOB is scheduled to run, not on your local database!!!!!

Export information from the Oracle Database to a text file using PL/SQL.

nenu, September 26, 2002 - 4:24 pm UTC

Hi Tom, I have Window NT system both at client(my machine) and server machine. I was running the job from my machine logging on to the server. The directory "d:\frmstest" is created at the server. I did run the job at the server. And I am getting the same error.
The init.ora file is set with all the parameters required to run the job.

utl_file_dir = d:\frmstest
job_queue_processes = 1
job_queue_interval = 60

Sorry, for all the confusion.
Regards.

Tom Kyte
September 26, 2002 - 4:48 pm UTC

then stop using unix paths, you used a unix path in the dbms_job.submit.

You posted:

Thanks Much.
Regards.

select JOB, LAST_DATE, NEXT_DATE, WHAT, THIS_SEC, NEXT_SEC, INTERVAL from
dba_jobs;

declare
l_job number;
begin
dbms_job.submit( l_job,
'declare
n int;
begin
n := dump_csv( ''select sysdate from dual'',
'','',
''/frmstest'',
''test008.txt'');
end;',
sysdate + 2 / 1440,
'sysdate + 2 / 1440' );
commit;
end;
/



and that is clearly a unix path.


Do this:


select job, what from user_jobs


post that result.

Export information from the Oracle Database to a text file using PL/SQL.

nenu, September 26, 2002 - 5:01 pm UTC

Tom, I run the below procedure and I have also displayed the results.
Thanks Much.
Regards.

declare
          l_job number;
    begin
         dbms_job.submit( l_job,
               'declare
                   n int;
                begin
                    n := dump_csv( ''select FUND, TYPE from frmsfund_xref'',
                                   '','',
                                  ''d:/frmstest'',
                                  ''test.txt'');
               end;',
              sysdate + 2 / 1440,
             'sysdate + 2 / 1440' );
          commit;
      end;
   /

Results:

SQL> select job, what from user_jobs;

       JOB
----------
WHAT
--------------------------------------------------------------------------------
         8
declare
                   n int;
                begin
                    n := dump_csv( 'select FUND, TYPE from frmsfund_xref',
                                   ',',
                                  'd:/frmstest',
                                  'test.txt');
               end;

       JOB
----------
WHAT
-------------------------------------------------------------------------------- 

Tom Kyte
September 26, 2002 - 6:27 pm UTC

d:/

whats up with that.


use the same thing as you use with utl_file_dir. But anyway. do this for us:


declare
n int;
begin
n := dump_csv( 'select FUND, TYPE from frmsfund_xref',
',',
'd:/frmstest',
'test.txt');
end;
/

exec dbms_job.run( 8 )

and cut and paste those exact steps from sqlplus..... if you have access to v$parameter, also do


show parameter utl


is there any limitation on how big a long could grow in memory?

P, September 26, 2002 - 7:57 pm UTC

hi tom,
we are usig to generate a report and store it in database
when I test my procedure with 40 records it works just fine but as soon as I go to 50 pages it gives me error
*********
SQL> /
DECLARE
*
ERROR at line 1:
ORA-06502: PL/SQL: numeric or value error
ORA-06512: at "NCDBMEL.PKG_SYSTEM_REPORTS", line 86
ORA-06512: at "NCDBMEL.PKG_SYSTEM_REPORTS", line 327
ORA-06512: at "NCDBMEL.PKG_SYSTEM_REPORTS", line 369
ORA-06512: at line 9
***********

well our process is something like this

cursor for loop
 longvar := longvar || append retrieved text to long  
 longvar := longvar || carriage return
 if lines > 35 then page break
 if pages = 1000 then insert into table (long variable)
 longvar = null;
end cursor for loop

there could be 100< no. of file < 200 files per report
is there any limitation on using long in stored procedures? 

Tom Kyte
September 26, 2002 - 8:15 pm UTC

Looks like you've gone over the 32k limit for PLSQL variables -- a long in PLSQL is really a varchar2(32k)

You probably (definitely) want to use a CLOB.


insert into table .... values ( ... , empty_clob() )
returning clob_col into l_clob;

cursor for loop
dbms_lob.writeAppend( l_clob, length(text), text );
if lines > 35 then writeappend page break;
if pages = 1000 then
insert into table .... values ( ... , empty_clob() )
returning clob_col into l_clob;
end loop



Help with Errors

Robert Ware, September 27, 2002 - 10:07 am UTC

Tom,

First, I want to thank you for all that you do and the invaluable information you have provided us with. Also, I want to share this with everybody as I have found it very useful.

When using utl_file, the following exception handling block could help you find problems with your implementation.


EXCEPTION
WHEN UTL_FILE.INVALID_PATH then
RAISE_APPLICATION_ERROR (-20101, 'UTL FILE: Invalid Path');
WHEN UTL_FILE.INVALID_MODE then
RAISE_APPLICATION_ERROR (-20102, 'UTL FILE: Invalid Mode');
WHEN UTL_FILE.INVALID_OPERATION then
RAISE_APPLICATION_ERROR (-20103, 'UTL FILE: Invalid Operation');
WHEN UTL_FILE.INTERNAL_ERROR then
RAISE_APPLICATION_ERROR (-20104, 'UTL FILE: Internal Error');
WHEN UTL_FILE.INVALID_FILEHANDLE then
RAISE_APPLICATION_ERROR (-20105, 'UTL FILE: Invalid File Handle');
WHEN UTL_FILE.WRITE_ERROR then
RAISE_APPLICATION_ERROR (-20106, 'UTL FILE: OS Error occurred during write operation');
WHEN OTHERS then
v_errorcode := SQLCODE;
v_errortext := SUBSTR(SQLERRM, 1, 200);
RAISE_APPLICATION_ERROR (-20999, v_errortext);
end;


These and other utl_file errors are documented in Oracle expert one-on-one pages 1202-1203 and on OTN at:
</code> http://download-west.oracle.com/docs/cd/A87860_01/doc/index.htm <code>

Re:is there any limitation on how big a long could grow in memory?

P, September 27, 2002 - 12:05 pm UTC

thank you tom for your clarification
I have on equestion though if LONG is 32K in PLSQL then
why CLOB should work?
so CLOB doesnt have 32K limitation in PL/SQL?


Tom Kyte
September 27, 2002 - 1:59 pm UTC

The clob isn't an "in memory variable".

It is a database object -- when you dbms_lob.write to a clob that you inserted - you are writing to the database (or temp if it is a dbms_lob.createtemporary lob)

Export information from the Oracle Database to a text file using PL/SQL.

nenu, September 27, 2002 - 1:02 pm UTC

Hi Tom, It works. It dumps the file after every 2 mins. I changed the integer to number in the dbms_job.submit call.
Thanks for all the help!
Regards.

Here's what i am doing:
declare
l_job number;
begin
dbms_job.submit( l_job,
'declare
l_rows number;
begin
l_rows := dump_csv( ''SELECT
OBLI_MONTH,
OBLI_FY,
OBLI_PROGUIC_UIC,
OBLI_FUND_CODE,
OBLI_YTD_ADJ_OBS
FROM
DUMP'',
'','',
''d:\frmstest'',
''test09.dat'' );
end;',
sysdate + 2 / 1440,
'sysdate + 2 / 1440' );
commit;
end;
/


Tom Kyte
September 27, 2002 - 2:34 pm UTC

and fixed the path -- which is ultimately what fixed it for you.

This was blowing up on the fopen call, not even remotely related to the datatype of l_rows.

using CLOB in memory

DADA, September 27, 2002 - 2:08 pm UTC

tom why are you using insert statement again inside
if pages = 1000 then

**************
insert into table .... values ( ... , empty_clob() )
returning clob_col into l_clob;

cursor for loop
dbms_lob.writeAppend( l_clob, length(text), text );
if lines > 35 then writeappend page break;
if pages = 1000 then
--WHY INSERT and NOT UPDATE
insert into table .... values ( ... , empty_clob() )
returning clob_col into l_clob;
end loop


Tom Kyte
September 27, 2002 - 2:53 pm UTC

you'd have to ask P from LA, it's their code. I was just redoing it with a clob.

long variable in plsql

P, September 27, 2002 - 3:30 pm UTC

hi tom,
in my pseudo code i have only 1 insert statement in yours you have 2
I guess his question is why do you have 2 insert statements
-------
dada
we are trying to generate and store report in a oracle table
P

Tom Kyte
September 27, 2002 - 3:53 pm UTC

really?

when I read:

cursor for loop
longvar := longvar || append retrieved text to long
longvar := longvar || carriage return
if lines > 35 then page break
if pages = 1000 then insert into table (long variable)
longvar = null;
end cursor for loop


I see you are building a page, inserting it when there are 1000 pages. So, every 1000 pages -- New row (i ASSUME there must be an insert at the bottom of your code, else the first 999 pages would go into the great bit bucket in the sky right)


I inserted a row -- put 1000 pages in it, insert a row, put a 1000 pages in it.

Just like your psuedo code.


but, you should do what you really mean to do, of course.

clob in plsql

dada, September 27, 2002 - 4:39 pm UTC

yes tom there should an insert at the end

otherwise LAST (not first - i guess you wanted to say last) 999 pages will not be written to DB
anyway
***
so in your pseudo code when you say
insert ...returning ;
append ;
--append is really update am I right?



Tom Kyte
September 27, 2002 - 4:55 pm UTC

correct, thanks. the "last" 999 pages will not be inserted....


append is

dbms_lob.writeAppend( to the clob the new text )


Their psuedo had a row for every 1000 pages, that is what I was trying to emulate. Insert a row -- writeAppend 1000 pages to the clob, insert a new row, writeappend 1000 pages to the clob and so on.

Export information from the Oracle Database to a text file using PL/SQL.

nenu, September 30, 2002 - 11:25 am UTC

Hi Tom, The procedure runs on the 7th day of the month at midnight. Were do we set the Time in the parameters Interval, Next_Date if the procedure had to run on the 7th day of the month at 5 o'clock in the morning.
Thanks Much.
Regards.

This is what the procedure does now:
add_months(trunc(sysdate,'month'),1)+6,
'add_months(trunc(sysdate,''month''),1)+6'

Tom Kyte
October 01, 2002 - 9:11 am UTC

'add_months(trunc(sysdate,''month''),1)+6+5/24'


Export information from the Oracle Database to a text file using PL/SQL.

nenu, October 01, 2002 - 10:51 am UTC

Thanks Much Tom.
Should i use 'add_months(trunc(sysdate,''month''),1)+6+5/24'
only for the parameter Interval or also for the parameter Next_Date.

Regards.

Tom Kyte
October 02, 2002 - 9:24 am UTC

depends, they are different parameters

one says when to first run it, the other says "here is the formula to compute the next time to run"

if you want the first run at 5am, you need to use that 5/24, else it runs at midnight.

Export information from the Oracle Database to a text file using PL/SQL.

nenu, October 02, 2002 - 10:36 am UTC

Hi Tom,The procedure needs to run at 5.00 am every 7th day of the month. So, I need to have both the next_date and the interval as same. I tried running it for next day and it needn't work. But, when i run it the same day e.g. sysdate+17/24, it runs.
Thanks Much.
Regards.

The below job didn't work:

declare
l_job number;
begin
dbms_job.submit( l_job,
'declare
l_rows number;
begin
l_rows := dump_csv( ''SELECT
OBLI_MONTH,
OBLI_FY,
OBLI_PROGUIC_UIC,
OBLI_FUND_CODE,
OBLI_YTD_ADJ_OBS
FROM
DUMP
ORDER BY OBLI_PROGUIC_UIC,OBLI_FUND_CODE'',
'' '',
''d:\frmstest'',
''CNSPBORS.txt'' );
end;',
trunc(sysdate,'month')+16/24,
'trunc(sysdate,''month'')+16/24' );
commit;
end;
/


Tom Kyte
October 02, 2002 - 11:11 am UTC

trunc(sysdate,'month')+6+5/24,
'add_months(trunc(sysdate,''month''),1)+6+5/24' );
commit;
end;

I have *no idea* why you were using what you did, no idea at all.

next_date and interval should be *similar* not the same. next_date needs to evaluate to NEXT MONTH right?

If you schedule this before the 7th day of the month, the above is what you want to use. If you schedule this on or after the 7th day of the month, they would be the same.

Very helpful reply

Rahul Priyadarshi, January 10, 2003 - 12:11 am UTC

Hi Tom,

This solution was very helpful to me as I had coded a similar senario of dumping a database to flat file.

Though I did not come across this problem as my data size did not exceed the limit but I will implement this in the code so that such a problem does not arrise.

Line Size GreaterTThan 32 k

A Reader, August 08, 2003 - 12:36 am UTC

hi tom ..
if line size is greater than 32k then ?

Tom Kyte
August 10, 2003 - 11:23 am UTC

you won't be using utl_file.

We mat avoid

Tathagat, September 12, 2003 - 4:38 pm UTC

CREATE OR REPLACE FUNCTION Dump_Csv( p_query IN VARCHAR2,
p_separator IN VARCHAR2 DEFAULT ',',
p_dir IN VARCHAR2 ,
p_filename IN VARCHAR2,p_max_linesize IN NUMBER DEFAULT 32000 )
-- 'p_max_linesize' this is due to your linesize exceeding THE DEFAULT LIMIT OF 1022 bytes/line.
-- WHEN you fopen THE FILE
-- you can specify a maxlinesize upto 32k. The default is 1022.

RETURN NUMBER
IS
l_output UTL_FILE.FILE_TYPE;
l_theCursor INTEGER DEFAULT DBMS_SQL.OPEN_CURSOR;
l_columnValue VARCHAR2(2000);
l_status INTEGER;
file_dir VARCHAR2(40);
l_colCnt NUMBER DEFAULT 0;
l_separator VARCHAR2(10) DEFAULT '';
l_cnt NUMBER DEFAULT 0;
BEGIN
-- This line is to avoid error because of wrong p_dir name
-- utl_file_dir init.ora parameter. Has to be set by DBA and
-- user should have the privilege to execute this command;
SELECT VALUE INTO file_dir FROM v$parameter WHERE NAME ='utl_file_dir';

l_output := UTL_FILE.FOPEN( file_dir, p_filename, 'w', p_max_linesize );

DBMS_SQL.PARSE( l_theCursor, p_query,
dbms_sql.native );

FOR i IN 1 .. 255 LOOP
BEGIN
DBMS_SQL.DEFINE_COLUMN( l_theCursor, i,
l_columnValue, 2000 );
l_colCnt := i;
EXCEPTION
WHEN OTHERS THEN
IF ( SQLCODE = -1007 ) THEN EXIT;
ELSE
RAISE;
END IF;
END;
END LOOP;

DBMS_SQL.DEFINE_COLUMN( l_theCursor, 1,
l_columnValue, 2000 );

l_status := DBMS_SQL.EXECUTE(l_theCursor);

LOOP
EXIT WHEN ( DBMS_SQL.FETCH_ROWS(l_theCursor) <= 0 );
l_separator := '';
FOR i IN 1 .. l_colCnt LOOP
DBMS_SQL.COLUMN_VALUE( l_theCursor, i,
l_columnValue );
UTL_FILE.PUT( l_output,
l_separator || l_columnValue );
l_separator := p_separator;
END LOOP;
UTL_FILE.NEW_LINE( l_output );
l_cnt := l_cnt+1;
END LOOP;
DBMS_SQL.CLOSE_CURSOR(l_theCursor);

UTL_FILE.FCLOSE( l_output );
RETURN l_cnt;
END Dump_Csv;
/


Tom Kyte
September 12, 2003 - 7:57 pm UTC

thats not too wise.

utl-file-dir is typically NOT just a directory name.

you should sort of know where you are writing to, period.

spool to text

Santhanam, September 13, 2003 - 7:44 am UTC

Tom nice example

cheers


You saved me again!

Pat, January 12, 2004 - 4:20 pm UTC

I've been seeing those clueless user-defined exception error messages, no idea what was going on - doesn't make any sense at all. Then decided to try your forum, and voila! The first link returned solved the problem. Just add the 32000 line size.

Even found answer to my next question: what if line size is over 32k.

Thanks so much, as always!

Tom Kyte
January 13, 2004 - 1:14 am UTC

you can use a BFILE to read the file by "chunks" of 32k into a raw, then use utl_raw.cast_to_varchar2 to convert it into a varchar2.

but plsql will have a 32k variable limit regardless -- you would have to be processing the data yourself -- not as a big line.

backup of all ddl objects

George DALLA, July 29, 2004 - 9:00 am UTC

hi

In our company we have a big oracle database and we want to generate in a simple script all the ddl scripts of all our tables, indexes, views, trigers and procedures what do we have to do?

if you have an answer please send it very soon

NB: please comment your code

thank you

theDALLA

Tom Kyte
July 29, 2004 - 12:58 pm UTC

seems like you should already have that, but....

SQL> desc dbms_metadata

 

follow up of backup of all ddl objects

theDALLA, July 30, 2004 - 5:43 am UTC

tom

i am using oracle 8.1.7.0.0 there is no dbms_metadata

furthermore i tried to use the UTL_FILE but when i have added the utl_file_dir to the init.ora nothing has changed: i am executing the command 

SQL> show  parameter utl_file;

this is the "answer"

NAME                                 TYPE    VALUE
------------------------------------ ------- -------
utl_file_dir                         string


please tell me what i have to do

thank you

theDALLA 

Tom Kyte
July 30, 2004 - 4:39 pm UTC

when no version supplied, I assume "software created this century" :)


anyway -- bounce your database for utl_file_dir to "take place"

and you can:

exp userid=/ owner=foo rows=n
imp userid=/ full=y indexfile=foo.sql


foo.sql will have most all of the stuff -- not the code though. for that search for

getcode getallcode

on this site (if you have my book Expert one on one Oracle -- see the chapter on export/import, i cover this in detail)

create ddl procedures

theDALLA, August 18, 2004 - 5:01 am UTC

Hi Tom
I want to create all ddl procedures and I have no idea how to do it
my ORACLE version is 8.1.7.0.0 and i can not use import/export, i have to write a procedure for this job, could you please help me?

By the way I wrote a procedure for the views and triggers and i getted the text from the system tables all_triggers and all_views what i hae to do for the procedures? (there is no all_procedures)

Tom Kyte
August 18, 2004 - 8:25 am UTC

why cannot you use export import?

first of all, you should already have the ddl somewhere (if not, someone needs to ask "why").

secondly, writing a ddl extraction tool is something that would literally take you weeks -- days to get the basics together, weeks to cover all of the bases.

Or, you can just use export and be done with it.


to get the code out, search this site for "getcode" "getallcode" - i have those scripts.

Ora.init

selva, December 02, 2004 - 12:22 am UTC

DECLARE
CURSOR EMP_REC IS
SELECT SNAME,AGE
FROM ARC;
rec emp_rec%ROWTYPE;
my_file utl_file.file_type;
cpath varchar2(100) := 'c:\selva';
cfail varchar2(15) := 'ex.csv';
BEGIN
-- Open the file for writing
my_file := utl_file.fopen(cpath,cfail,'w');
-- Read all records from EMP and write into file
FOR rec IN emp_rec LOOP
utl_file.putf(my_file,REC.SNAME||'|'||REC.AGE||'\n');
-- I use | to delimit fields
END LOOP;
-- Now close the file
utl_file.fclose(my_file);
END;

when i run the procedure i get this error.
what is the loacation of the ora.init and what will i do there?
Thanks in advance
ORA-06510: PL/SQL: unhandled user-defined exception
ORA-06512: at "SYS.UTL_FILE", line 98
ORA-06512: at "SYS.UTL_FILE", line 157
ORA-06512: at line 11

Tom Kyte
December 02, 2004 - 7:34 am UTC

from my book "Expert one on one Oracle"


<quote>
Handling Exceptions

UTL_FILE throws exceptions when it encounters an error. Unfortunately, it uses user-defined exceptions - exceptions it has defined in its package specification. These exceptions, if not caught by name, produce the following less then useful error message:

ERROR at line 1:
ORA-06510: PL/SQL: unhandled user-defined exception
ORA-06512: at "SYS.UTL_FILE", line 98
ORA-06512: at "SYS.UTL_FILE", line 157

This tells you nothing about the error itself. In order to solve this issue, we have to surround our calls to UTL_FILE with an exception block that catches each of the exceptions by name. I prefer to then turn these exceptions into RAISE_APPLICATION_ERROR exceptions. This allows me to assign an ORA- error code and supply a more meaningful error message. We used this in the preceding example to turn the above error message into:

ORA-20001: INVALID_PATH: File location or filename was invalid.

Which is much more useful. The block I always use for this is:

exception
when utl_file.invalid_path then
raise_application_error(-20001,
'INVALID_PATH: File location or filename was invalid.');
when utl_file.invalid_mode then
raise_application_error(-20002,
'INVALID_MODE: The open_mode parameter in FOPEN was
invalid.');
when utl_file.invalid_filehandle then
raise_application_error(-20002,
'INVALID_FILEHANDLE: The file handle was invalid.');
when utl_file.invalid_operation then
raise_application_error(-20003,
'INVALID_OPERATION: The file could not be opened or
operated on as requested.');
when utl_file.read_error then
raise_application_error(-20004,
'READ_ERROR: An operating system error occurred during
the read operation.');
when utl_file.write_error then
raise_application_error(-20005,
'WRITE_ERROR: An operating system error occurred
during the write operation.');
when utl_file.internal_error then
raise_application_error(-20006,
'INTERNAL_ERROR: An unspecified error in PL/SQL.');
end;

I actually keep this in a small file and read it into each routine that uses UTL_FILE to catch the exception and 'rename it' for me.
</quote>

A reader, September 28, 2005 - 2:35 pm UTC


number data type doesn't work

A reader, May 28, 2009 - 5:05 pm UTC

Hi Tom,
I have number fields has position 38 or 9, by using the following and it doesn't work for me...
ELSIF ( l_descTbl(i).col_type = 2 ) THEN -- number type
L_descTbl(i).col_max_len := l_descTbl(i).col_precision+2;

Please help!!
Tom Kyte
May 28, 2009 - 5:32 pm UTC

give an ENTIRE example with data and tell us what you expected and what you got. In short, show us "what didn't work" Don't make us page up and down - be complete and self contained. Don't assume we'll look at old code above - especially since people have a tendency to change it and not say anything and there could be many versions of it above.

"it doesn't work for me" is so vague and nebulous as to be impossible to even consider addressing.

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