I receive a file that has:
- an header, starting with the string header followed by some columns;
- a body: all the other lines after the first one (the header).
I know that only the header will begin with the string 'HEADER' so I thought I could check it using a WHEN condition in my control file, this is necessary because I have to insert the content of the header in a table and the body in another table, so I created the following control file:
OPTIONS (READSIZE=512000000,bindsize=512000000,rows=64000, ERRORS=100000)
LOAD DATA
characterset UTF8 length semantics byte
REPLACE
INTO TABLE <TABLE_1>
WHEN (1:6) != 'HEADER'
fields terminated by "|"
TRAILING NULLCOLS
(
ANNO INTEGER EXTERNAL,
COD_PRODOTTO CHAR(12) "TRIM (:COD_PRODOTTO)",
DESCRIZIONE_PRODOTTO CHAR(254) "TRIM (SUBSTRB(:DESCRIZIONE_PRODOTTO,1,254))",
COD_PADRE CHAR(12) "TRIM (:COD_PADRE)",
FOGLIA CHAR(1) "TRIM (:FOGLIA)",
COD_STRUTTURA CHAR(10) "TRIM (:COD_STRUTTURA)",
TIPO_STRUTTURA CHAR(10) "TRIM (:TIPO_STRUTTURA)"
)
INTO TABLE <TABLE_2>
WHEN (1:6) = 'HEADER'
fields terminated by "|"
TRAILING NULLCOLS
(
HEADER FILLER,
ANNO INTEGER EXTERNAL,
COD_STRUTTURA CHAR(12) "TRIM (:COD_STRUTTURA)",
TIPO_STRUTTURA CHAR(12) "TRIM (:TIPO_STRUTTURA)",
TIPO_INVIO CHAR(5) "TRIM (:TIPO_INVIO)",
DATA_RICEZIONE "sysdate"
)
but I obtain that the body rows are correctly inserted but not the header's ones (it says that "ANNO" is an invalid number, but is not).
The "cool" part is that if I invert the wheres the header is inserted and not the body (invalid "ANNO" again).
Looking at the log it seems it read the structure of the two tables ignoring the wheres, like it is the content of a single table, because I have:
Column Name Position Len Term Encl Datatype
------------------------------ ---------- ----- ---- ---- ---------------------
ANNO FIRST * | CHARACTER
COD_PRODOTTO NEXT 12 | CHARACTER
SQL string for column : "TRIM (:COD_PRODOTTO)"
DESCRIZIONE_PRODOTTO NEXT 254 | CHARACTER
SQL string for column : "TRIM (SUBSTRB(:DESCRIZIONE_PRODOTTO,1,254))"
COD_PADRE NEXT 12 | CHARACTER
SQL string for column : "TRIM (:COD_PADRE)"
FOGLIA NEXT 1 | CHARACTER
SQL string for column : "TRIM (:FOGLIA)"
COD_STRUTTURA NEXT 10 | CHARACTER
SQL string for column : "TRIM (:COD_STRUTTURA)"
TIPO_STRUTTURA NEXT 10 | CHARACTER
SQL string for column : "TRIM (:TIPO_STRUTTURA)"
Table <TABLE_2>, loaded when 1:6 = 0X484541444552(character 'HEADER')
Insert option in effect for this table: REPLACE
TRAILING NULLCOLS option in effect
Column Name Position Len Term Encl Datatype
------------------------------ ---------- ----- ---- ---- ---------------------
HEADER NEXT * | CHARACTER
(FILLER FIELD)
ANNO NEXT * | CHARACTER
COD_STRUTTURA NEXT 12 | CHARACTER
SQL string for column : "TRIM (:COD_STRUTTURA)"
TIPO_STRUTTURA NEXT 12 | CHARACTER
SQL string for column : "TRIM (:TIPO_STRUTTURA)"
TIPO_INVIO NEXT 5 | CHARACTER
SQL string for column : "TRIM (:TIPO_INVIO)"
DATA_RICEZIONE NEXT * | CHARACTER
SQL string for column : "sysdate"
So the second one starts with NEXT and not with FIRST, so I think all the columns are shifted.
I tried to add "POSITION(1) FILLER" for the second table but I obtain other errors about the types.
What is wrong in my control file?
Here's a simplified example of what you're doing. Why simplified? Because you didn't provide test case, and I didn't feel like typing that much.
Sample tables:
Control file; it contains data to be loaded. I'm loading header table first, body next:
Loading session & the result:
The way I see it, the key moment is to instruct SQL*Loader to reprocess the same file again. How? By setting the
position
:As you can see, both tables were loaded, containing all sample rows.