Why I can't use sign '<' or '>' in when clause? - oracle

I use sql loader for load data in my database. For example, I want load records only from certain range, but I get this message:
My control file:
LOAD DATA
INFILE 'C:\sql\empl.dat'
BADFILE 'C:\sql\empl.bad'
DISCARDFILE 'C:\sql\empl.dat.dsc'
INTO TABLE LOAD_EMP_N
WHEN empno<'5600'
FIELDS TERMINATED BY "|"
(empno,ename CHAR, job CHAR,mgr,
hiredate DATE "DD-MM-YYYY", sal,comm,
deptno)
If I change when clause
WHEN empnŠ¾='5600' -- all work!!
I can't understand what is the problem?

Quote from the SQL*Loader manual
A field condition is a statement about a field in a logical record that evaluates as true or false. It is used in the WHEN, NULLIF, and DEFAULTIF clauses.
...
operator A comparison operator for either equal or not equal.
So in other words: the when condition in a SQL*Loader control files only supports = or <>

Related

How can I use a '>' or '<' in the when clause of a control file?

LOAD DATA
INFILE 'Sample2.dat'
APPEND INTO TABLE EMP_LEAVE
WHEN REQUEST_DATE > SYSDATE --The problem lies here
FIELDS TERMINATED BY ","
(REQUEST_NO,
EMPNO,
REQUEST_DATE DATE "DD-MM-YYYY",
START_DATE DATE "DD-MM-YYYY",
END_DATE DATE "DD-MM-YYYY",
REASON,
LEAVE_TYPE,
NO_OF_DAYS,
APPROVAL
)
I'm trying to insert only those rows where the REQUEST_DATE is higher than the current date. Any idea how I could do that?
As far as I can tell, you can't directly from SQL*Loader.
WHEN clause, which is used to conditionally load records, accepts only "equal" or "not equal" operators, i.e. =, <> or !=, i.e. you can't use "greater than" > and similar.
For more info, see this:
A field condition is a statement about a field in a logical record
that evaluates as true or false. It is used in the WHEN, NULLIF,
and DEFAULTIF clauses.
(...)
operator: A comparison operator for either equal or not equal.
So, what to do?
load data into a temporary table and then extract rows you want
instead of SQL*Loader, use external tables feature which lets you write a query against it (i.e. you're directly accessing the file as if it were an "ordinary" table, so you can use any WHERE clause you want, including where request_date > sysdate)

loading data in table using SQL Loader

I'm loading data into my table through SQL Loader
data loading is successful but i''m getting garbage(repetitive) value in a particular column for all rows
After inserting :
column TERM_AGREEMENT is getting value '806158336' for every record
My csv file contains atmost 3 digit data for that column,but i'm forced to set my column definition to Number(10).
LOAD DATA
infile '/ipoapplication/utl_file/LBR_HE_Mar16.csv'
REPLACE
INTO TABLE LOAN_BALANCE_MASTER_INT
fields terminated by ',' optionally enclosed by '"'
(
ACCOUNT_NO,
CUSTOMER_NAME,
LIMIT,
REGION,
**TERM_AGREEMENT INTEGER**
)
create table LOAN_BALANCE_MASTER_INT
(
ACCOUNT_NO NUMBER(30),
CUSTOMER_NAME VARCHAR2(70),
LIMIT NUMBER(30),
PRODUCT_DESC VARCHAR2(30),
SUBPRODUCT_CODE NUMBER,
ARREARS_INT NUMBER(20,2),
IRREGULARITY NUMBER(20,2),
PRINCIPLE_IRREGULARITY NUMBER(20,2),
**TERM_AGREEMENT NUMBER(10)**
)
INTEGER is for binary data type. If you're importing a csv file, I suppose the numbers are stored as plain text, so you should use INTEGER EXTERNAL. The EXTERNAL clause specifies character data that represents a number.
Edit:
The issue seems to be the termination character of the file. You should be able to solve this issue by editing the INFILE line this way:
INFILE'/ipoapplication/utl_file/LBR_HE_Mar16.csv' "STR X'5E204D'"
Where '5E204D' is the hexadecimal for '^ M'. To get the hexadecimal value you can use the following query:
SELECT utl_raw.cast_to_raw ('^ M') AS hexadecimal FROM dual;
Hope this helps.
I actually solved this issue on my own.
Firstly, thanks to #Gary_W AND #Alessandro for their inputs.Really appreciate your help guys,learned some new things in the process.
Here's the new fragment which worked and i got the correct data for the last column
LOAD DATA
infile '/ipoapplication/utl_file/LBR_HE_Mar16.csv'
REPLACE
INTO TABLE LOAN_BALANCE_MASTER_INT
fields terminated by ',' optionally enclosed by '"'
(
ACCOUNT_NO,
CUSTOMER_NAME,
LIMIT,
REGION,
**TERM_AGREEMENT INTEGER Terminated by Whitspace**
)
'Terminated by whitespace' - I went through some threads of SQL Loader and i used 'terminated by whitespace' in the last column of his ctl file. it worked ,this time i didn't even had to use 'INTEGER' or 'EXTERNAL' or EXPRESSION '..' for conversion.
Just one thing, now can you guys let me now what could possibly be creating issue ?what was there in my csv file in that column and how by adding this thing solved the issue ?
Thanks.

Import CSV which every cell terminated by newline

I have CSV file. The data looks like this :
PRICE_a
123
PRICE_b
500
PRICE_c
1000
PRICE_d
506
My XYZ Table is :
CREATE TABLE XYZ (
DESCRIPTION_1 VARCHAR2(25),
VALUE NUMBER
)
Do csv as above can be imported to the oracle?
How do I create a control.ctl file?
Here's how to do it without having to do any pre-processing. Use the CONCATENATE 2 clause to tell SQL-Loader to join every 2 lines together. This builds logical records but you have no separator between the 2 fields. No problem, but first understand how the data file is read and processed. SQL-Loader will read the data file a record at a time, and try to map each field in order from left to right to the fields as listed in the control file. See the control file below. Since the concatenated record it read matches with TEMP from the control file, and TEMP does not match a column in the table, it will not try to insert it. Instead, since it is defined as a BOUNDFILLER, that means don't try to do anything with it but save it for future use. There are no more data file fields to try to match, but the control file next lists a field name that matches a column name, DESCRIPTION_1, so it will apply the expression and insert it.
The expression says to apply the regexp_substr function to the saved string :TEMP (which we know is the entire record from the file) and return the substring of that record consisting of zero or more non-numeric characters from the start of the string where followed by zero or more numeric characters until the end of the string, and insert that into the DESCRIPTION_1 column.
The same is then done for the VALUE column, only returning the numeric part at the end of the string, skipping the non-numeric at the beginning of the string.
load data
infile 'xyz.dat'
CONCATENATE 2
into table XYZ
truncate
TRAILING NULLCOLS
(
TEMP BOUNDFILLER CHAR(30),
DESCRIPTION_1 EXPRESSION "REGEXP_SUBSTR(:TEMP, '^([^0-9]*)[0-9]*$', 1, 1, NULL, 1)",
VALUE EXPRESSION "REGEXP_SUBSTR(:TEMP, '^[^0-9]*([0-9]*)$', 1, 1, NULL, 1)"
)
Bada-boom, bada-bing:
SQL> select *
from XYZ
/
DESCRIPTION_1 VALUE
------------------------- ----------
PRICE_a 123
PRICE_b 500
PRICE_c 1000
PRICE_d 506
SQL>
Note that this is pretty dependent on the data following your example, and you should do some analysis of the data to make sure the regular expressions will work before putting this into production. Some tweaking will be required if the descriptions could contain numbers. If you can get the data to be properly formatted with a separator in a true CSV format, that would be much better.

using multiple conditions in sql loader

I was trying to load records from a file to an oracle table based on conditions. Since OR operator and WHEN IN statements do not work in sql loader, I tried multiple insert to a table. However, only the records that match the first condition were loaded in the table and the records that matched the second condition were not loaded. My control file looks like below:
Options (BINDSIZE = 7340032)
Load Data
APPEND
INTO TABLE TEMP_GLOBAL_ONE_FEE_REBATE WHEN ACT_TYPE = 'SR'
FIELDS TERMINATED BY '|' TRAILING NULLCOLS
(
RPT_YEAR,
RPT_MONTH,
........
........
)
INTO TABLE TEMP_GLOBAL_ONE_FEE_REBATE WHEN ACT_TYPE = 'SL'
FIELDS TERMINATED BY '|' TRAILING NULLCOLS
(
RPT_YEAR,
RPT_MONTH,
........
........
)
** As mentioned, only those records with act_type = 'SR' were loaded and those records with act_type = 'SL' were not loaded.
Any idea how to go on this? Thank you.
Your problem is that the first INTO command reads the file from beginning to end, and then the second INTO command picks up where the first one finished - which is the end of the file in your case.
To achieve what you are trying to do, you're gonna have to use two seperate sql loader commands. See this post on AskTom for reference -
https://asktom.oracle.com/pls/apex/f?p=100:11:::YES:RP:P11_QUESTION_ID:3181887000346205200
A more elegant solution would be reading the data from the file using a pl/sql procedure and UTL_FILE package, but this is only worth the trouble if the import is something that happens a lot, and not a one time thing.
You should use POSITION(1) in the first column of each field list:
To force record scanning to start in a specific location, you use the POSITION parameter.
Control file
Options (BINDSIZE = 7340032)
Load Data
APPEND
INTO TABLE TEMP_GLOBAL_ONE_FEE_REBATE WHEN ACT_TYPE = 'SR'
FIELDS TERMINATED BY '|' TRAILING NULLCOLS
(
RPT_YEAR POSITION(1),
RPT_MONTH,
........
........
)
INTO TABLE TEMP_GLOBAL_ONE_FEE_REBATE WHEN ACT_TYPE = 'SL'
FIELDS TERMINATED BY '|' TRAILING NULLCOLS
(
RPT_YEAR POSITION(1),
RPT_MONTH,
........
........
)
Sample data
2015|01|SL
2015|02|SL
2015|03|SL
2015|03|SR
2015|04|SR
2015|04|XX
This will load 2 rows with 'SR', 3 rows with 'SL', and discard one row.
References
SQL*Loader with multiple WHENs is rejecting all rows, the Ask Tom queston mentioned in the accepted answer
Distinguishing Different Input Record Formats in SQL*Loader Control File
Loading Data into Multiple Tables in SQL*Loader Control File Reference

Oracle SQLLDR Discard rows using WHEN clause not working

I am trying to load a text file, only those rows where 3rd column 'c_nbr' Doesn't END with 'ABCD'. Since WHEN clause is really primitive I could not use, trim/substring with it.
My second choice was to put the last 4 chars of c_nbr field to a column called 'MSGCOL' and use that column in my WHEN clause, like " WHEN MSGCOL <> 'ABCD' ".
The MSGCOL is getting value "ABCD" where column 'c_nbr' ends with "ABCD", but the WHEN clause is not DISCARDing them.
Why it's not working? How can I achieve my goal? Can I run SQL Query from sqlldr control file itself? Like "Delete from tbl_load where c_nbr like '%ABCD';" at the end of loading commands?
SQLLDR Control File:-
OPTIONS (ERRORS=9999)
LOAD DATA
INFILE '052140.csv'
BADFILE '052140.BAD'
DISCARDFILE '052140.DIS'
INFILE '055913.csv'
BADFILE '055913.BAD'
DISCARDFILE '055913.DIS'
APPEND INTO TABLE tbl_load
WHEN MSGCOL <> 'ABCD'
FIELDS TERMINATED BY ',' optionally enclosed by '"' trailing nullcols
(
id "TRIM(UPPER(:ID))",
pid,
c_nbr "TRIM(:c_nbr)",
a_nbr "SUBSTR(TRIM(:a_nbr), 1, 25)",
P_REASON2 FILLER,
MSGCOL EXPRESSION "substr(trim(:c_nbr), length(trim(:c_nbr))-3, 4)"
)

Resources