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

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

Related

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

AS400 Emulator cant process dates less than 1940 or greater than 2039

I have this simple SQL script:
SELECT DATE(SUBSTR( '19310205' , 1 , 4)
|| '-' || SUBSTR ('19310205' , 5 , 2)
|| '-' || SUBSTR('19310205', 7 , 2))
FROM MY_TABLE;
Whenever I run the script on the iSeries navigator, I get the expected output which is
1931-02-05
However, when I run it on the AS400 Emulator using the strsql command, I get the following output:
++++++++
I have no idea why this happens; all I know is that only the dates between 1940-2039 are working well. Can anyone explain why?
Also, is there a way for the other dates be processed successfully as well?
In your AS/400 emulator session, press "F13=Services".
Select "1. Change Session Attributes"
Change the "Date Format" to "*ISO" or desired format supporting a full date range.
From the IBM Knowledge Center, "Rational Developer for i7.1.0":
A date is a three-part value (year, month, and day) designating a point in time >under the Gregorian calendar20, which is assumed to have been in effect from >the year 1 A.D. The range of the year part is 0001 to 9999. The date formats >*JUL, *MDY, *DMY, and *YMD can only represent dates in the range 1940 through >2039. The range of the month part is 1 to 12. The range of the day part is 1 to >x, where x is 28, 29, 30, or 31, depending on the month and year.
I just want to build on Richard Evans answer, but since there is too much to put into a comment, I will make it a new answer.
IBM i has a native date type that can store dates from January 1, 0001 to December 31, 9999. The date type has a format which specifies, among other things, the number of digits in the year portion of the date. There are two main groupings that affect the range of dates that can be accepted. Two digit year formats which can accept dates from January 1, 1940 - December 31, 2039. These are: *MDY, *DMY, *YMD, and *JUL. Four digit year formats can handle the full range of dates that the date type supports. These are *ISO, *USA, *EUR, *JIS.
In addition to the main formats which are supported everywhere date formats are supported, RPG supports a few other date formats: *JOBRUN, three digit year formats, and *LONGJUL. *JOBRUN is a two digit year format, and can only be specified for numeric and character date fields with 2 digit years. This uses the job date format and seperator values. Three digit year formats can handle dates from January 1, 1900 - December 31, 2899. These are *CMDY, *CDMY, and *CYMD. The C in the three digit year formats represents the two most significant digits of the year portion of the date where:
0 => 1900 - 1999
1 => 2000 - 2099
2 => 2100 - 2199
...
9 => 2800 - 2899
Finally *LONGJUL is a four digit year Julian format.
Internally dates are stored in an *ISO format. The other formats are external formats. In fact when defining tables with SQL you don't even get to specify the date format, it just defaults to *ISO. In places that you can specify the format, it is just an external format that you are specifying. It is best to use *ISO for all working fields and database files, even when using DDS. Then reserve other external formats like *MDY or *DMY for user facing fields to convert the *ISO format into a more localized format. This way you can store the full range of dates that users can input or view.
Return a character representation of a date in any format using the varchar_format() function. Regardless of session defaults or where its run from.
SELECT
cast(
varchar_format(
cast(
DATE(SUBSTR( '19310205' , 1 , 4)
|| '-' || SUBSTR ('19310205', 5 , 2)
|| '-' || SUBSTR('19310205', 7 ,2))
as timestamp )
, 'YYYY-MM-DD')
as char(10)) as mydate
FROM sysibm/sysdummy1
MYDATE
1931-02-05
******** End of data ********

Searching Between Two Dates With A Specific Format

So I have a table where the dates are formatted as such: 15-Jan-13
That would obviously be January 15th, 2013.
The problem is, when I try to search a date range between 01/01/2014 and SYSDATE, it errors out.
Does anyone know the proper way in which I would format this based off of how my dates are stored?
FYI my raw data is stored as: 15-JAN-13 02.23.27.000000000 PM -05:00
I'm converting it as
TRUNC(variable_name)
Given that you are asking about "sysdate" then I would assume you are using Oracle. It would also seem that the the column with the dates are not actual in the date format. Best option would be to change the column to a date type. If for some reason that isn't an option, the next best thing to do is to translate the text to a date as part of your query:
select *
from foo
where to_date(your_column, 'dd-Mon-yy') between to_date('01/01/2014', 'mm/dd/yyyy')
and sysdate
Note that to_date is expecting it's second argument to match the structure of the date specified so '01/01/2014' would match the date format 'mm/dd/yyyy' and your_column (value: '15-Jan-13') would match a different format 'dd-Mon-yy'. Once everything is translated to a date, Oracle can perform appropriate date comparisons.
DISCLAIMER: The translation of your_column to a date using to_date means that if an index is defined on your_column, it won't be used. If this is a large table you can expect sub-optimal performance. One additional reason to change the column data type to a date.

Oracle varchar2 to date conversion

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

Do the TO_DATE function in Oracle 11g PL/SQL have upper/lower limits

I am new to Oracle development and am still discovering a lot of it's capabilities and the differences between PL/SQL and SQL Server's T-SQL.
So my 'project' is to create a function that would generate a random date from either the future or the past. The user should be able to specify the upper/lower bounds in which the date should be created.
I may be too late but in the interest of breivity I will skip the details of why the function does what it does and how. What is important and pertinent to the actual questions is the following behavoir.
BEGIN
SYS.DBMS_OUTPUT.PUT_LINE(TO_DATE(TRUNC(SYSDATE + 6469), 'yyyy/mm/dd')); -- Dec 31, 2031
SYS.DBMS_OUTPUT.PUT_LINE(TO_DATE(TRUNC(SYSDATE - 4853), 'yyyy/mm/dd')); -- Jan 01, 2001
SYS.DBMS_OUTPUT.PUT_LINE(TO_DATE(TRUNC(SYSDATE + 7000), 'yyyy/mm/dd')); -- ERROR
END
Simply put, when I add enough days to the SYSTEM date to exceed Dec 31, 2031 I get the following error message ... "a non-numeric character was found where a numeric was expected" ... . I experience the same problem when I subtract enough days from the SYSTEM date to pre-date Jan 01, 2001.
When I remove the format it's doesn't break but returns an impossible date ...
BEGIN
-- returns 15-JUN-33
-- June 33rd 2015!!
SYS.DBMS_OUTPUT.PUT_LINE(TO_DATE(TRUNC(SYSDATE + 7000)));
END
So it appears to me that there is some sort of date range limit on this function ... JAN 01, 2001 - DEC 31, 2031 ... Is that true or am I doing something wrong here?
Thanks!
Let's work through the data types here.
sysdate returns a date. Adding a number to a date returns a date that many days in the future. So, for example, sysdate + 7000 is June 15, 2033. trunc(sysdate + 7000) also returns a date, it just sets the time to midnight. So far, so good.
The problem comes when you take that date and pass it to the to_date function. Logically, that doesn't make sense. You already have a date, there is no need to convert it to a date. Practically, to_date does not accept a date as a parameter. It only accepts a string. Now, Oracle can implicitly convert the date you have to a string using your session's nls_date_format setting which is what it does here. Best case, you're taking a date, implicitly converting that to a string, then explicitly converting that string back to exactly the same date that you started with. If your session's nls_date_format happens not to match the format mask that you're providing to the to_date, however, you'll likely get an error which is what you're seeing here.
Walking through an example, let's use the date of midnight on June 15, 2033. If you call to_date on that, Oracle has to convert the date to a string using your session's nls_date_format. If you're in the United States and you haven't changed anything about your client, your nls_date_format is probably DD-MON-RR. That means that your date gets converted to the string 15-JUN-33 when it is passed in to to_date. So, logically, you're trying to do something like
dbms_output.put_line( to_date( '15-JUN-33', 'yyyy/mm/dd' ));
When you look at it this way, it's obvious that the format mask doesn't match the format of the string which causes an error. If your nls_date_format is closer to the format mask in your to_date, it is possible that the to_date call will run successfully but return a different date than you expect (switching the month and the day for example).
The simple answer is that you should never call to_date on a day. You should only call to_date on a string. If you want to convert a date into a string in a particular format for display, use to_char not to_date.
Going back to the original question, yes there are limits to what constitutes a valid date in Oracle. A valid date must be between Jan 1, 4712 BC (6700 years ago) to Dec 31, 9999 (7900 years from now). It doesn't appear that you are anywhere near exceeding those limits.