Reformat date in SQL Loader - oracle

I am loading Oracle tables using SQL Loader and I have an issue with date formats. The CSV files with the data contain strings in the format YYYY-MM-DD HH:MM:SS, but the Oracle tables require date format of DD-MON-YY.
I am currently going through the CSV files line by line to look for and reformat any dates before the load, but the files can reach 10M+ rows and this can be a pretty slow process. Does SQL Loader allow date reformatting in the load?
I'm looking for something like
LOAD DATA
INFILE 'data.csv'
TRUNCATE
INTO TABLE data
FIELDS TERMINATED BY '|'
TRAILING NULLCOLS
(
COL1,
COL2,
CREATED_DATE DATE 'DD-MON-YY',
LAST_UPDT_DATE DATE 'DD-MON-YY
)
I've read suggestions that this DATE command can format dates automatically but has given no luck so far.

Assuming created_date and last_updt_date are actually defined as date in the database, they don't have a format. They're stored in an internal packed binary format that is not human readable.
Your control file needs to specify the format of the strings in the flat file that represent the date. You say the format is "YYYY-MM-DD HH:MM:SS" but that doesn't make sense. Minutes are MI not MM so I assume that is a type. HH is a 12 hour time format but that doesn't make sense without an AM/PM indicator. So I'm guessing your strings are using a 24 hour time format which is HH24. So my guess is that you want
CREATED_DATE DATE 'YYYY-MM-DD HH24:MI:SS',

Related

Converting date from DD-MON-YY to DD-MM-YYYY with NLS_DATE_FORMAT

I'm trying to store date type data from Oracle FORMS with format mask as like DD-MM-YYYY but every time it store as like DD/MON/YY.
I already alter session with NLS_DATE_FORMAT, but result is as same as before.
Oracle internal date format that is written in the table is something you can't change in any way, but, in the same time, it is irrelevant. If you are dealing with DATE type column then you should know that it containes both the date and the time. How, where and when you will show it or use it is on you. Here is a sample of a few formats derived from that original Oracle DATE format...
WITH
t AS
(
Select SYSDATE "MY_DATE_COLUMN" From Dual
)
Select
MY_DATE_COLUMN "DATE_DEFAULT_FORMAT",
To_Char(MY_DATE_COLUMN, 'mm-dd-yyyy') "DATE_1",
To_Char(MY_DATE_COLUMN, 'yyyy/mm/dd') "DATE_2",
To_Char(MY_DATE_COLUMN, 'dd.mm.yyyy') "DATE_3",
To_Char(MY_DATE_COLUMN, 'dd.mm.yyyy hh24:mi:ss') "DATE_4"
From t
DATE_DEFAULT_FORMAT
DATE_1
DATE_2
DATE_3
DATE_4
22-OCT-22
10-22-2022
2022/10/22
22.10.2022
22.10.2022 10:59:44
You can find a lot more about the theme at https://www.oracletutorial.com/oracle-basics/oracle-date/
Regards...
In Oracle, a DATE is a binary data-type consisting of 7-bytes (representing century, year-of-century, month, day, hour, minute and second). It ALWAYS has those 7 components and it is NEVER stored in any particular human-readable format.
every time it store as like DD/MON/YY.
As already mentioned, no, it does not store a date like that; the database stores dates as 7 bytes.
What you are seeing is that the client application, that you are using to connect to the database, is receiving the 7-byte binary date value and is choosing to convert it to something that is more easily comprehensible to you, the user, and is defaulting to converting the date to a string with the format DD/MON/RR.
What you should be doing is changing how the dates are displayed by the client application by either:
Change the settings in the Toad (View > Toad Options > Data Grids > Data and set the Date Format option) and allow Toad to implicitly format the string; or
Use TO_CHAR to explicitly format the date (TO_CHAR(column_name, 'DD-MM-YYYY')).
I'm trying to store data as like DD-MM-YYYY.
If you want to store a date then STORE it as a date (which has no format) and format it when you DISPLAY it.
If you have a valid business case to store it with a format then you will need to store it as a string, rather than as a date, because you can format strings; however, this is generally considered bad practice and should be avoided.
Sadman, to add to what others have posted I suggest you do not write your applications with reliance on the NLS_DATE_FORMAT parameter but rather you screens and application should specify the expected DATE entry format and the code should use the TO_DATE function to store the data into the database. All application SQL should use the TO_CHAR function to format date output for display.

Change timestamp format in oracle

I am getting timestamp format as '01-APR-21 12.02.00.496677000 AM' from oracle, I want to change the format to load data into sql server column with datatype as datetime.
Current Input: '01-APR-21 12.02.00.496677000 AM'
Expected Output : 2021-04-01 12:02:00.496
I need to write the code in oracle to change timestamp format
Thanks
Neha
A TIMESTAMP is a binary data format consisting of 7-20 bytes (century, year-of-century, month, day, hour, minute, second, up to 6 bytes for fractional seconds and up to 7 bytes for time zone information); it does NOT have a format.
Why am I seeing the TIMESTAMP with a format?
You are seeing it with a format because whatever user interface you are using to access the database has decided that it is more useful to display the binary information as a formatted string rather than returning the raw byte values to you.
Typically, for SQL/Plus and SQL Developer, this is managed by the NLS_TIMESTAMP_FORMAT session parameter. Other user interfaces will have different mechanisms by which they manage the default format of dates and timestamps.
If you want to change the default for SQL/Plus (and SQl Developer) then you can use:
ALTER SESSION SET NLS_TIMESTAMP_FORMAT = 'YYYY-MM-DD HH24:MI:SS.FF9';
(Or whatever format you would like.)
How can I format the TIMESTAMP value?
If you then want to display the timestamp with a format (remember, a TIMESTAMP is not stored with any format) then you want to use TO_CHAR to convert it to a string where it can have a format.
If you want to format the TIMESTAMP as a YYYY-MM-DD HH24:MI:SS.FF3 string then use:
SELECT TO_CHAR( your_timestamp_column, 'YYYY-MM-DD HH24:MI:SS.FF3' )
FROM your_table
How can I convert a formatted string back to a TIMESTAMP?
From your comment:
I loaded the oracle data into a different SQL table where date format was varchar and data got loaded as '01-APR-21 12.02.00.496677000 AM'
Use TO_TIMESTAMP:
SELECT TO_TIMESTAMP( your_string_column, 'DD-MON-RR HH12:MI:SS.FF9 AM' )
FROM your_table
(Note: that this will convert your string to a binary TIMESTAMP and then whatever user interface you are using will use its rules on how to display it; and if the default format it is using is DD-MON-RR HH12:MI:SS.FF9 AM then the query above will look like it has done nothing; it has, the UI is just implicitly converting it back to a string to display it.)

Oracle sqlldr timestamp format issue

I'm having an issue getting sqlldr to import a DAT file data file into my table, specifically with the field that is a timestamp.
2018-11-02T20:54:38.000000+0000
I've tried all manner of combinations in my control file and am going around in circles. Does anyone know what should be using in my control file for this above timestamp format?
For reference, this is what I've most recently tried:
load data
infile 'feed.dat'
into table cust_acct
fields terminated by "|"
( ...
updateddatetime TIMESTAMP "YYYY-MM-DD-HH24.MI.SS",
...)
The date 2018-11-02T20:54:38.000000+0000 has a time-zone component so you want TIMESTAMP WITH TIME ZONE data type and you have 6 fractional seconds digits so your data type should have precision of 6.
In a DateTime format model you can use double quotes to indicate a literal string and, in sqlldr you can escape the double quotes with a backslash:
updateddatetime TIMESTAMP(6) WITH TIME ZONE "YYYY-MM-DD\"T\"HH24:MI:SS.FF6TZR",
or
updateddatetime TIMESTAMP(6) WITH TIME ZONE "YYYY-MM-DD\"T\"HH24:MI:SS.FF6TZHTZM",

If-else case in SQL*Loader

I need to insert NULL into the table whenever the SQL*Loader encounters a bad date (0000-00-00 00:00:00) while reading a .csv file.
The bad date provided in the csv is always 0000-00-00 00:00:00.
I need help figuring out the case for it that handles both a bad date and a correct date.
There are two cases:
Date in the correct format (YYYY/MM/DD hh24:mi:ss)
Date in the bad format (0000-00-00 00:00:00)
Initially I had a simple statement in SQL control file as below, now I need to add the case to handle bad date as well.
START_DATE DATE "YYYY/MM/DD hh24:mi:ss" NULLIF (START_DATE = "NULL").
I need an SQL*Loader statement that handles both the above cases.
All data in a file is essentially a string until validated as a different datatype. So, you can treat it as a string for the bad data before converting it into a date:
START_DATE "TO_DATE(NULLIF(:START_DATE, '0000-00-00 00:00:00'), 'yyyy/mm/dd hh24:mi:ss')"
I'm a little concerned that the format of the "bad" date is different to that of the good date. It indicates something is going on that you're maybe not aware of for instance the data coming from two different systems or this field not being stored as a date in the source system.
If possible, I'd double check how this data is being constructed and what the intended meaning of the bad date is.

How to load files using SQLLDR with date format as yyyymmddhhmmss?

I need to load a table with a .csv file which contains date "20140825145416".
I have tried using (DT date "yyyymmdd hh24:mm:ss") in my control file.
It throws an error as ORA-01821: date format not recognized
I require the data in table as "MM/DD/YYYY HH:MM:SS".
Sample data : 20140825145416
thanks in advance.
Well, I would be remiss if I did not point out that the correct answer is to never store dates as VARCHAR2 data, but make it a proper DATE column and load it like this:
DT DATE "YYYYMMDDHH24MISS"
Formatting is done when selecting. It will make your life so much easier if you ever need to use that date in a calculation.
That out of the way, If you have no control over the database and have to store it as a VARCHAR2, first convert to a date, then use to_char to format it before inserting:
DT CHAR "to_char(to_date(:DT, 'YYYYMMDDHH24MISS'), 'MM/DD/YYYY HH24:MI:SS')"
Note 'MI' is used for minutes. You had a typo where you used 'MM' (months) again for minutes.
I know it's already been said in the previous answer, but it's so important, it's worth repeating. Do not store dates as varchars !!
If your DT column is timestamp then this might work
DT CHAR(25) date_format TIMESTAMP mask "yyyymmddhhmiss"
I used something like this in external tables. Maybe this might help
https://docs.oracle.com/cd/B19306_01/server.102/b14215/et_concepts.htm
and
https://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:8128892010789

Resources