Oracle varchar2 to date conversion - sql

I have one table in oracle database which has one column of type varchar2 and it stores date. the problem is it store date in 2 character year format like 19/08/66 which is equivalent to the 19/08/1966. But when i convert this date using to_date function, it returns 19/08/2066 but expecting 19/08/1966. how can i convert it properly.

If I remember Oracle correct the to_datefunction accepts a format_mask and if you use this mask: 'DD/MM/RRRR' values between 0-49 will return a 20xx year and values between 50-99 will return a 19xx year. So try this:
to_date('19/08/66', 'DD/MM/RRRR')

Use to_date function.
TO_DATE('16/06/66','DD/MM/RRRR')
Output is
16/06/1966
TO_DATE('16/06/16','DD/MM/RRRR')
Output is
16/06/2016
TO_DATE('16/06/16','DD/MM/RRRR') when u have run this query in 1940s
Output is
16/06/1916
The logic Oracle follows as below the function accepts a 2-digit year and returns a 4-digit year.
A value between 0-49 will return a 20xx year.
A value between 50-99 will return a 19xx year.

Try this:
with t as(
select '16/06/66' str from dual
)
select to_date(str, 'DD/MM/YY') after, to_date(str, 'DD/MM/RR') before
from t
AFTER BEFORE
----------------------
06/16/2066 06/16/1966

Related

concatenate with leading zeros for months - not a valid month error

I want to concatenate string with year in oracle. The string is month.
Query is
select to_date('11'||EXTRACT(YEAR FROM SYSDATE)-1,'MMYYYY') from dual;
This query wrks fine however if the string is '01' or anything starting with zero i am getting not a valid month error.
select to_date('04'||EXTRACT(YEAR FROM SYSDATE)-1,'MMYYYY') from dual;
select to_date('05'||EXTRACT(YEAR FROM SYSDATE)-1,'MMYYYY') from dual;
Let's run it without the to_date(..., ...) wrapper:
select '04'||EXTRACT(YEAR FROM SYSDATE)-1 from dual;
'04'||EXTRACT(YEARFROMSYSDATE)-1
--------------------------------
42019
Do you see the problem? (Note that the result is a number, not even a string.)
Concatenation is performed before you subtract 1. You get the string '042020' first, and then you subtract 1; the string is converted to number, and you get the result 42019. When you apply TO_DATE() this is converted back to string, and the first thing Oracle will choke on is the 42 for month.
Use parentheses around the arithmetic operation to force the subtraction to be performed first, and it will work:
select to_date('04'||(EXTRACT(YEAR FROM SYSDATE)-1), 'MMYYYY') from dual;
TO_DATE('04'||(EXTR
-------------------
2019-04-01 00:00:00

How to extract month number from date in Oracle

I have ID_BB_SECURITY column where the date value is stored in this column for example '20190801'.
I want to get month number from this field for example for August date i want to get 8.
I tried below query but it throws an error 'literal does not match':
select to_number(to_date(ID_BB_SECURITY),'mm') from BT_EXPORT
I am not sure if i have to ignore null values so as to avoid the error
If the value is a number or string then you can convert it to a date with an appropriate mask - which is what you are missing, and what is causing the error you are getting (as it's using your session's NLS_DATE_FORMAT setting, which apparently does not match the format of the data; but which you should not rely on anyway, as #MTO said in comments):
to_date(ID_BB_SECURITY, 'YYYYMMDD')
and then extract the month number from that:
select extract(month from to_date(ID_BB_SECURITY, 'YYYYMMDD')) from BT_EXPORT
Or you could just use a substring:
select to_number(substr(ID_BB_SECURITY, 5, 2)) from BT_EXPORT;
Those assume a fixed consistent format, which is always a risky assumption when using the wrong data type. Ans if it's a number they are doing an implicit conversion from number to string, which you could turn into an explicit conversion for greater clarity.
If it's already a date - as it should be, of course - then you don't need the conversion:
select extract(month from ID_BB_SECURITY) from BT_EXPORT
If you have a number, you can use arithmetic to extract the month:
select mod(floor(20190801 / 100), 100)
from dual;
You could try converting the number date to a string, and then extracting the 5th and 6th characters:
SELECT
SUBSTR(TO_CHAR(ID_BB_SECURITY), 5, 2) AS mm
FROM BT_EXPORT;
But, it would be much better for you to use a proper date column. Then, you could use a less draconian method such as:
SELECT
TO_CHAR(ID_BB_SECURITY, 'mm') AS mm -- assuming date
FROM BT_EXPORT;
select to_number(to_char(to_date('20190801', 'yyyymmdd'), 'mm')) from dual
Try this one
select extract(month from to_date(ID_BB_SECURITY, 'YYYYMMDD')) from BT_EXPORT
This one convert number to date then extract month.
also
select extract(month from to_date('20190801', 'yyyymmdd')) from dual
Your date column has the value stored in the following format "yyyymmdd" where
yyyy is the year
mm the month
dd the day
So in order to return the number value of the month (mm) we can do as follows:
1: first transform the value from a number to a date using
to_date(20190801,'yyyymmdd')
2: get month using to_date operator
to_char( to_date(20190801,'yyyymmdd'), 'mm')

How to write the code in Oracle SQL (like 'CCYYMMDD' into 102 )

How to write the code in Oracle SQL (like 'CCYYMMDD' into 102 )?
If someone will enter the date in the frontend, the value should return as 102 instead of date.
For that, how will write the function in Oracle PLSQL.
https://www.unece.org/trade/untdid/d00a/tred/tred2379.htm
These are the ANSI standard format.
You cannot write a function to determine which numeric date string corresponds to which format as the date string could be multiple formats:
For example, 010203 could be:
Format 2: DDMMYY 1st February 03
Format 3: MMDDYY 2nd January 03
Format 101: YYMMDD 3rd February 01
Format 306: DDHHMM 02:03 of Day 1
Format 402: HHMMSS 01:02:03
Format 405: MMMMSS 102 minutes 3 seconds
Format 610: CCYYMM March 0102
Format 616: CCYYWW Week 3 of 0102
Similarly 10080102 could be:
Format 4: DDMMCCYY 10th August 102
Format 102: CCYYMMDD 2nd January 1008
Format 305: MMDDHHMM 8th October 01:02
Format 501: HHMMHHMM Time span from 10:08 to 01:01
If anyone inserts the date in this format "CCYYMMDD" then the value should return only 102 as a default in the frontend. How to write the code in SQL?
You cannot, as I described above it is ambiguous what some values are and they could return multiple formats. Instead you should create another column and store the date format in that when the user inputs the date rather than trying to reconstruct the format code from an (ambiguous) number.
You can verify that a string fits a date format like this:
create or replace function is_CCYYMMDD
(p_str in varchar2)
return boolean
is
rv boolean;
dt date;
begin
begin
dt := to_date(p_str, 'YYYYMMDD');
dt := to_date('2000' || substr(p_str, 5), 'YYYYMMDD');
rv := true;
exception
when others then
rv := false;
end;
return rv;
end;
The first to_date() just checks that the whole string is a valid date. The second to_date() checks that the second half of the string is a valid month and day combo. This partly addresses #MTO observations about the problems of enforcing a strict format when some strings can fit more than one format.
Note that it is perfectly possible to have valid dates which pass this test despite being ambiguous e.g. is 20111012 in 'YYYYMMDD' or 'DDMMYYYY'? There is no way to be sure unless you enforce strict date formatting in the front-end input by using a date picker widget or separate input boxes for year, month and day.
why you pass '2000' in this query?
The second check verifies that the last four characters are valid as month and day. Whenever we do this sort of test we run into the problem of leap years. If we just apply to_date(str, 'MMDD') Oracle will default the year to the current year: the snag is 2018029 is not a valid date even though the original input of 20160229 is valid. My function avoids this by fixing the year element to 2000, which was a leap year.
Incidentally, if you want to use this function in SQL you'll need to change the return datatype to varchar2 (Y/N flag) or a number (1/0) because SQL doesn't support Booolean.
If you want to convert an Oracle date into a Julian date, then you can use the TO_CHAR function with 'j' as the format.
SELECT TO_CHAR(TO_DATE('BC47120412', 'BCYYYYMMDD'), 'J')
FROM DUAL;
Output: 0000102
If you want to convert julian date to oracle date then use query below,
SELECT TO_DATE(102, 'J')
FROM DUAL;
Output: 04/12/4712 12:00:00 AM BC

To get all the dates in a format dd/mm/yyyy. I have a date field in the format yyyymmdd

In my DB, there is a date field in the format yyyymmdd.
I have to get all the dates in the format dd-mm-yyyy for that particlar date.
ex:
Date
20170130
20170228
20170325
for the above dates, I need the output in the below format with the dates and day of the particular dates
date day
30-01-2017 tuesday
28-02-2017 tuesday
25-03-2017 saturday
If the column is a string, then it can hold invalid date values such as February 31, one way to avoid this is by a small function such as this:
create or replace
function my_to_date( p_str in varchar2 ) return date
is
begin
return to_date( p_str );
exception
when others then
return null;
end;
\\
select to_char(my_to_date('20170231'),'DD-MM-YYYY Day')
from dual
\\
Demo
Try below:
Select to_char(yrdate, 'dd-mm-yyyy'), to_char(yrdate, 'D') from yrtable
It sounds like your dates aren't actually DATE fields but some kind of CHAR field? The best option would be to convert to DATE and then convert back to CHAR:
SELECT TO_CHAR(TO_DATE(mydate, 'YYYYMMDD'), 'DD-MM-YYYY Day')
FROM mytable;
This uses the YYYYMMDD mask to convert your string into a date, then uses the mask DD-MM-YYYY Day to convert it back into a string. Use day if you want the day name in lowercase (as in your OP).
#user2778168 answer will give you the results you want. But why?
Your database does not have dates stored in yyyymmdd format or any other date format for at mater, unless it's defined with a character type definition. Oracle stores all dates in a single internal structure, and with only slight variations timestamps are the same. The format used only tells Oracle how to display the value or to convert a string to a date. Unless a specific format is specified Oracle uses the NLS_DATE_FORMAT for this determination. See here and scan down to "Datetime Format Models" for format specifications.
To see this run the following:
select value
from nls_session_parameters
where parameter = 'NLS_DATE_FORMAT';
Select yrdate default_format
, to_char(yrdate, 'dd-mm-yyyy') specified_format
, dump(yrdate) unformated
from yrtable;
alter session set nls_date_format = 'Month dd,yyyy';
Rerun the above queries.
It seems you hold date column(date1) in character format. Suppose you have a table named days:
SQL> desc days
date1 varchar2(10)
then,
we should convert it into date, and then into char format, with aliases in quotation marks to provide lowercase aliases as you wanted.
perhaps your database's date language is non-english like mine(turkish), then you need to convert it to english.
lastly, it'a appropriate to order the results according to converted date, seen from your output. So we can use the following SQL :
select to_char(to_date(date1,'yyyymmdd'),'dd-mm-yyyy') "date",
to_char(to_date(date1,'yyyymmdd'),'day','nls_date_language=english') "day"
from days
order by to_date(date1,'yyyymmdd');
D e m o

to_date function strange behaviour for specific year

Different behaviour ,when the date contains year 2000
select to_date(add_months(sysdate,-50),'dd/mm/yyyy') from dual --error
ORA-01858: a non-numeric character was found where a numeric was expected
-- 04/08/2000 12:59:15 contains year 2000
select to_date(sysdate,'dd/mm/yyyy') from dual --this work,but diff output
You should use TO_CHAR instead of TO_DATE.
The first parameter of TO_DATE function is a STRING parameter so here your data is converted to STRING representation and then converted to date format BUT in the DIFFERENT format:
to_char(add_months(sysdate,-50),'dd/mm/YYYY')
Your first query select to_date(add_months(sysdate,-50),'dd/mm/yyyy') from dual works fine for me
Result:
TO_DATE(ADD_MONTHS(SYSDATE,-50),'DD/MM/YYYY')
---------------------------------------------
04-OCT-09