Subject: How to Pass the Input File with Variable Names to SQL*Loader Dynamically
  Doc ID: 191043.1 Type: HOWTO
  Modified Date : 19-SEP-2008 Status: PUBLISHED

Checked for relevance on 19-SEP-2008 

PURPOSE
-------

SQL*Loader cannot handle variable input file names. This can be needed for 
periodic loads to Oracle database with file names changing each time.
This article shows four workarounds to use variable input file names with 
SQL*Loader.

 
SCOPE & APPLICATION
-------------------

This article is helpful for SQL*Loader users need to load from input files
with variable names. It covers four detailed workaround examples.


How to Pass the Input File with Variable Names to SQL*Loader Dynamically
------------------------------------------------------------------------
 
SQL*Loader cannot handle variable input file names. The parameter INFILE
specified in the control file doesn't allow variable names - if the name of the
data file is changed, then the control file must be edited and the name of the 
inputfile must also be changed.

This article describes 4 workarounds, how to pass the input file to SQL*Loader
dynamically, without changing the control file every time the input file name 
is changed.

For a better understanding we will consider the following test case:

-- The table to be loaded
CREATE TABLE LDR_TEST
(
   ID    NUMBER,
   TEXT  VARCHAR2(10)
);

-- Input data records (file LDR.DAT)
1;Text 1
2;Text 2
3;Text 3

1. The simplest method to do this is to rename the input file (accordingly to 
the control file parameter INFILE). If the control file (LDR1.CTL) was 
defined as:

LOAD DATA
INFILE 'LDR.DAT'
TRUNCATE
INTO TABLE LDR_TEST
FIELDS TERMINATED BY ";"
(
  ID,
  TEXT
)

then every new input file must be renamed to LDR.DAT before starting the 
load process.

******************
*                *
*    SAMPLE 1    *
*                *
******************
----------------------------- Shell begin -----------------------------

#!/bin/sh
# This shell (LOAD.SH) renames the input file name ($1) 
# to LDR.DAT that will be later used by SQL*Loader.
# Note:  The shell must have at least 774 permissions to run. (chmod 774)
# This works only for UNIX platforms

# Rename (or copy) the file 
mv $1 LDR.DAT
# cp $1 LDR.DAT

# Start SQL*Loader with the new control file
sqlldr scott/tiger control=LDR1.CTL

------------------------------ Shell end ------------------------------

Change permissions for the LOAD.SH shell to -rwxrwxr--:

#> chmod 774 LOAD.SH

Start the shell with:

#> ./LOAD.SH /tmp/files/LDR.DAT

where /tmp/files/LDR.DAT is the new inputfile. 

2. Pass the data file to SQL*Loader with the command line parameter DATA.

In this case the control file (LDR2.CTL) doesn't contain the parameter INFILE.

LOAD DATA
TRUNCATE
INTO TABLE LDR_TEST
FIELDS TERMINATED BY ";"
(
  ID,
  TEXT
)

The data file is specified in the command line (parameter DATA).

******************
*                *
*    SAMPLE 2    *
*                *
******************
----------------------------- Shell begin -----------------------------

#!/bin/sh
# This shell (LOAD.SH) passes the inputfile ($1) to SQL*Loader through 
# the parameter DATA in command line

# Start SQL*Loader with the new control file
sqlldr scott/tiger control=LDR2.CTL data=$1

------------------------------ Shell end ------------------------------

Change permissions for the LOAD.SH shell to -rwxrwxr--:

#> chmod 774 LOAD.SH

Start the shell with:

#> ./LOAD.SH /tmp/files/LDR.DAT

where /tmp/files/LDR.DAT is the new inputfile. 

3. Use a pipe to transfer the data from data file to SQL*Loader. First, 
the records from the data file will be sent in a pipe, and then SQL*Loader 
will receive the records from the pipe and insert them in the database.

Due to Bug 1271684 this workaround can only be used in 8.1.6.3 and greater
on Unix platforms.

The command lines for different operating systems are the following:

VMS (7.2+) pipe type ldr.dat | sqlldr scott/tiger control=ldr3.ctl
UNIX       cat LDR.DAT | sqlldr scott/tiger control=LDR3.CTL
NT         type ldr.dat | sqlldr scott/tiger control=ldr3.ctl

The appropriate control files (LDR3.CTL) are these:

UNIX and NT
-----------
LOAD DATA
INFILE "-"
TRUNCATE
INTO TABLE LDR_TEST
FIELDS TERMINATED BY ";"
(
  ID,
  TEXT
)

VMS
---
LOAD DATA
INFILE SYS$INPUT
TRUNCATE
INTO TABLE TEST_LDR
FIELDS TERMINATED BY ";"
(
  ID,
  TEXT
)

******************
*                *
*    SAMPLE 3    *
*                *
******************
----------------------------- Shell begin -----------------------------

#!/bin/sh
# This shell (LOAD.SH) uses a pipe to pass input file ($1) to SQL*Loader.

# Start SQL*Loader with the new control file
cat $1 | sqlldr scott/tiger control=LDR3.CTL

------------------------------ Shell end ------------------------------

Change permissions for the LOAD.SH shell to -rwxrwxr--:

#> chmod 774 LOAD.SH

Start the shell with:

#> ./LOAD.SH /tmp/files/LDR.DAT

where /tmp/files/LDR.DAT is the new inputfile. 

4. Use a place holder in control file and automatically change it before 
starting the load process.

In this example the control file (LDR_TEMPLATE.CTL) looks like this:

LOAD DATA
INFILE $INPUT
TRUNCATE
INTO TABLE LDR_TEST
FIELDS TERMINATED BY ";"
(
  ID,
  TEXT
)

The idea is to programatically change the name of the place holder $INPUT 
before starting SQL*Loader. This will be done with the following UNIX shell:

******************
*                *
*    SAMPLE 4    *
*                *
******************
----------------------------- Shell begin -----------------------------

#!/bin/sh
# This shell (LOAD.SH) passes the input file name ($1) to the SQL*Loader
# control file - it searches the place holder $INPUT in the control file
# LDR_TEMPLATE.CTL, changes it to the new name ($1) and save it in the new 
# control file named LDR4.CTL. This file will be later used by SQL*Loader.

# Change the place holder
cat LDR_TEMPLATE.CTL | sed -e "s%\$INPUT%'$1'%" > LDR4.CTL

# Start SQL*Loader with the new control file
sqlldr scott/tiger control=LDR4.CTL

------------------------------ Shell end ------------------------------

Start the shell with:

#> ./LOAD.SH /tmp/files/LDR.DAT 

where /tmp/files/LDR.DAT is the new input file.

.