Skip to Main Content

Breadcrumb

Question and Answer

Tom Kyte

Thanks for the question, Percy .

Asked: May 02, 2000 - 1:20 pm UTC

Last updated: April 01, 2009 - 9:50 am UTC

Version:

Viewed 10K+ times! This question is

You Asked

Can I run SQL*Loader on the server from a database
procedure ? If yes, then How ?


and Tom said...



SQLLoader is a separate, command line program. This is similar to asking "can I run 'ls' from plsql". Using an external procedure (the ability to write a stored procedure in C) or by using a java stored procedure, we can run external commands like this.

If you have a smallish amount of data to load (eg: you recieve the name of a file with a couple of dozen/hundred records in it and wish to load it), you can also investigate using the builting UTL_FILE package. This lets plsql read/write text files on the server. If the data is binary in nature, the builtin datatype BFILE may be used to read binary data as well.



Rating

  (9 ratings)

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

Comments

Call sqlldr from stored procedure

Jie Yang, February 06, 2002 - 1:42 pm UTC

Your answer is at </code> http://asktom.oracle.com/pls/asktom/f?p=100:11:::::P11_QUESTION_ID:8812348049,%7Bsqlloader%7D%20and%20%7BAND%7D%20and%20%7Bprocedure%7D

But the answer at
http://www.orafaq.com/msgboard/serverutil/messages/2015.htm <code>

has a different view.

Can you take a look and see whether it is possible to implment that so that one can call sqlldr from a PL/SQL procedure?


Tom Kyte
February 08, 2002 - 9:40 am UTC

tell me, how is my answer:

Using an external procedure (the ability to write a
stored procedure in C) or by using a java stored procedure, we can run external
commands like this.

materially different from their answer:

You can use an external procedure (Oracle Version 8.0.5 and higher) to call sqlloader from a stored procedure in plsql

????




Loader plus triggers versus stored procedures plus UTL_FILE

Alexandre Matthes, February 08, 2002 - 6:14 pm UTC

Tom,

What is the best (fast) way to load a heavy amount of data weekly ???

Using SQLLoader loading flat files into non related tables and some triggers filling the related tables from those non related

OR

Using some stored procedures with UTL_FILE reading that same flat files and loading them to that same related tables

Thanks in advance,


Tom Kyte
February 09, 2002 - 11:48 am UTC

OR

skip the triggers and UTL_FILE stuff and go straight into the real tables? If I had to pre-process the data, I would either:

o use sqlldr to go straight into the REAL tables from the get go if possible

o write some C code to process and array insert the data into the REAL tables in the first place

o direct path load the data into a scratch table and using a stored procedure that employeed BULK COLLECTS and FORALL inserts -- process the data



SqlLoader from PL/SQL - what about password?

Ilya, May 22, 2004 - 3:31 pm UTC

Hi Tom,

I have a situation where I have to call sqlloader from inside a stored procedure, rather than external table, because one of the columns is > 4000 chars, so I have to load it into a CLOB column. I'm using a java stored procedure as a wrapper to call sqlloader. My question is what to do about password that I'll need to pass to the SQLLoader? I had these ideas:
1) make user pass the password as parameter to stored procedure, who will then pass it to sqlloader and also schedule itself in dbms_job. The disadvantage here is the user will have to manually restart the procedure everytime the database is restarted (i.e. on reboot)
2) encrypt the password in a stored procedure
3) store encrypted password (with DES encryption) in a stored procedure and store a key in some OS-protected file.
4) create a separate schema altogether, just for loading data from sql loader and nothing else, give stored procedure access to that schema, and also give it access to a stored procedure installed in sys that will let it change the password for that schema, so it can generate new password automatically and change the password for that schema when main procedure starts. Is this too crazy?
5) make the main program external to database (i.e. a service under NT) and use OS to store password and other initial parameters (in registry on NT or in unix in some secure file).

What would you suggest?

Also, do you see any time in the future when external tables might support CLOB columns? It's a real shame that anything 4000 (even if it's reasonably small, like 6000 chars) automatically becomes a CLOB.

thanks very much,
ilya

Tom Kyte
May 22, 2004 - 5:29 pm UTC

how many records are we talking about at a time here and how often?

and what does the file format look like?

RE: SqlLoader from PL/SQL - what about password?

A reader, May 23, 2004 - 5:01 pm UTC

The file may have anywhere between 1000 records (if it's a weekly load) or 50000 records (if the client wants to completely reload his list). The file format is delimited ASCII file (maybe about 30 columns per row), information about delimiter for row and columns is stored in a settings table.

thanks,
ilya

Tom Kyte
May 23, 2004 - 9:00 pm UTC

what about something like this:

create or replace directory test as '/home/tkyte'
/

drop table t;

create table t ( a number, b number, c varchar2(30), d varchar2(30), e varchar2(30), f clob);

declare
l_bfile bfile;
l_size number;
l_last number := 1;
l_current number;
l_clob clob;
l_rec t%rowtype;
l_comma raw(1) := utl_raw.cast_to_raw( ',' );
begin
l_bfile := bfilename( 'TEST', 'x.dat' );
dbms_lob.fileopen( l_bfile );
l_size := dbms_lob.getlength( l_bfile );


loop
dbms_application_info.set_client_info( l_last || ' of ' || l_size );

l_current := dbms_lob.instr( l_bfile, l_comma, l_last, 1 );
exit when (nvl(l_current,0) = 0);
l_rec.a := utl_raw.cast_to_varchar2(dbms_lob.substr( l_bfile, l_current-l_last, l_last ));
l_last := l_current+1;

l_current := dbms_lob.instr( l_bfile, l_comma, l_last, 1 );
exit when (nvl(l_current,0) = 0);
l_rec.b := utl_raw.cast_to_varchar2(dbms_lob.substr( l_bfile, l_current-l_last, l_last ));
l_last := l_current+1;

l_current := dbms_lob.instr( l_bfile, l_comma, l_last, 1 );
exit when (nvl(l_current,0) = 0);
l_rec.c := utl_raw.cast_to_varchar2(dbms_lob.substr( l_bfile, l_current-l_last, l_last ));
l_last := l_current+1;

l_current := dbms_lob.instr( l_bfile, l_comma, l_last, 1 );
exit when (nvl(l_current,0) = 0);
l_rec.d := utl_raw.cast_to_varchar2(dbms_lob.substr( l_bfile, l_current-l_last, l_last ));
l_last := l_current+1;

l_current := dbms_lob.instr( l_bfile, l_comma, l_last, 1 );
exit when (nvl(l_current,0) = 0);
l_rec.e := utl_raw.cast_to_varchar2(dbms_lob.substr( l_bfile, l_current-l_last, l_last ));
l_last := l_current+1;

insert into t (a,b,c,d,e,f) values (l_rec.a, l_rec.b, l_rec.c, l_rec.d, l_rec.e, empty_clob() )
returning f into l_rec.f;

l_current := dbms_lob.instr( l_bfile, '0A', l_last, 1 );
exit when (nvl(l_current,0) = 0);
dbms_lob.loadFromFile( l_rec.f, l_bfile, l_current-l_last+1, 1, l_last );
l_last := l_current+1;
end loop;
end;
/


to avoid the issue alltogether?

RE: SqlLoader from PL/SQL - what about password?

A reader, May 24, 2004 - 9:41 am UTC

Thanks, I'll try that.

Solution is great. but works only 50% for me. Please help

Ravi, June 01, 2004 - 5:02 pm UTC

Hi Tom,
I have tried the solution that you have given for loading a delimited data file into an Oracle table from Plsql (using dbms_lob). The given example doesn't seem to work 100%. if there are 12 records in the file, it loads only 5 etc. not sure, where and why it's missing other records. The only thing that I changed from your script is the stuff related to loading or reading any clob data (column f). could you please suggest if I am missing some thing..or how to make the script work to read complete data..Thaks in advance. Ravi

</code> http://asktom.oracle.com/pls/asktom/f?p=100:11:::::P11_QUESTION_ID:8812348049,%7Bsqlloader%7D%20and%20%7BAND%7D%20and%20%7Bprocedure%7D <code>

Tom Kyte
June 01, 2004 - 5:21 pm UTC

... The only thing that I changed
from your script....

you changed it.

so, give us, just like I give you, the COMPLETE example. show us YOUR variation and the 12 lines that don't work.


(better yet - if you are like me and are paid to write code for money.... what about debugging it? I cannot be the only one left that can do that can I?)

SqlLoader from PL/SQL . Super : )

Ravi, June 02, 2004 - 3:05 pm UTC

Hi Tom,
It now works great. I was able to find the problem. The problem was due to my wrong placement of the End-of-line read statement in my code.[ l_current := dbms_lob.instr( l_bfile, '0A', l_last, 1 )].

I have added the following line to my code to close the open file:
dbms_lob.fileclose(l_bfile );
Thank you for such a wonderful solution!



Can I run SQL*Loader on the server from a db

Sagar, April 01, 2009 - 8:40 am UTC

Hi, once you invoke cmd from pl/sql using java proc. then how to pass below command as parameter?
sqlldr userid= scott/tiger@host control= "C:\new\EmployeeData.ctl"

I am also refering link
http://www.astral-consultancy.co.uk/cgi-bin/hunbug/doco.cgi?11160



Tom Kyte
April 01, 2009 - 9:50 am UTC

not sure what you are asking here

but I would strongly encourage you to use an external table, then you do not need sqlldr at all.

Execute OS commands from pl/sql

JuanMa, January 31, 2014 - 11:34 am UTC

Hi,

As I know, you can execute os commands using 3 ways:

1 Coding a native shared library. A C compiler for the platform is required. It is described at the note "Calling Operating System Commands From PL/SQL Using External Procedures (Doc ID 99136.1)"

2 Using the package DBMS_SCHEDULER. The parameter job_type must be 'EXECUTABLE'. Nevertheless it lacks access to STDIN and STDOUT.

3 Using JVM, as Oracle explain in the document "Executing shell (operating system) commands from PL/SQL", refering link http://www.oracle.com/technetwork/database/enterprise-edition/calling-shell-commands-from-plsql-1-1-129519.pdf

regards



More to Explore

CLOB/BLOB/etc

Complete documentation on Securefiles and Large Objects here