Store date without time in oracle [duplicate] - sql

I have a date field in a table that contains date in dd-MMM-yy format .
I want to create a function that get this date check it for not null and then change it to yyyy/mm/dd format
but the problem is that oracle doesn't accept dd-MMM-yy formate date as a input parameter and
it say : Please Use yyyy-MM-dd date format !!!
how can I first change dd-MMM-yy formate to yyyy-MM-dd so oracle accept it as input then change it to yyyy/mm/dd

: Please Use yyyy-MM-dd date format !!!
That is no way related to an Oracle error.
I have a date field in a table that contains date in dd-MMM-yy format .
No, you are confused. Oracle does not store dates in the format you see. It stores it internally in 7 bytes with each byte storing different components of the datetime value.
Byte Description
---- -------------------------------------------------
1 Century value but before storing it add 100 to it
2 Year and 100 is added to it before storing
3 Month
4 Day of the month
5 Hours but add 1 before storing it
6 Minutes but add 1 before storing it
7 Seconds but add 1 before storing it
If you want to display, use TO_CHAR with proper FORMAT MODEL.
While inserting, use TO_DATE with proper FORMAT MODEL.
What you see as a format by default, is your locale specific NLS settings.
SQL> select parameter, value from v$nls_parameters where parameter='NLS_DATE_FORMAT';
PARAMETER VALUE
--------------- ----------------------------------------------------------------
NLS_DATE_FORMAT DD-MON-RR
SQL> select sysdate from dual;
SYSDATE
---------
03-FEB-15
SQL> select to_char(sysdate, 'mm/dd/yyyy hh24:mi:ss') from dual;
TO_CHAR(SYSDATE,'MM
-------------------
02/03/2015 17:59:42
SQL>
Update Regarding MMM format.
By MMM if you mean the month name up to three characters, then use MON.

Related

Adding a day in Oracle but losing hour and minute, and format is also changing

I have a table tab1 in which a column col1 has data type VARCHAR2(50 BYTE) and this column has values like '9/27/21 18:05'
I want to add 1 day to this and I am expecting a result like '9/28/21 18:05'
If I do
TO_TIMESTAMP(col1,'MM/DD/YYYY HH24:MI') + INTERVAL '1' DAY
then I get '28-SEP-21 06.24.00.000000000 PM', and if I do
TO_DATE(col1,'MM/DD/YYYY HH24:MI') + INTERVAL '1' DAY'
then I get '28-SEP-21'.
Please note in both the above cases format is changing.
How can I get the result I want?
DATE and TIMESTAMP values are both binary data types that do NOT have a given format; therefore, when you convert a string to a DATE or a TIMESTAMP then the format you use is NOT stored.
If you want to convert it to a DATE or TIMESTAMP and then back to a string in the same format then, after adding the interval, you want to use TO_CHAR to convert back to a string with the required format.
For example:
SELECT TO_CHAR(
TO_DATE(col1, 'MM/DD/RR HH24:MI') + INTERVAL '1' DAY,
'MM/DD/RR HH24:MI'
)
FROM tab1
Note: If you use YYYY in the format model then 21 will be parsed as 21 AD and not as 2021 AD. Instead, you need to use YY or RR (depending on how you want values from the end of the last century to be handled).
Please note in both the above cases format is changing.
The format of your column is not changing, you have converted the strings to DATE and TIMESTAMP which are binary data type and do not have any format.
The user interface you are using (i.e. SQL/Plus or SQL Developer) tries to be helpful and rather than presenting you, the user, with binary data will use its internal rules to format the binary data as something you can read. SQL/Plus and SQL Developer will use the NLS_DATE_FORMAT session parameter for DATE values and the NLS_TIMESTAMP_FORMAT session parameter for TIMESTAMP values. These parameters can be set to different values for each user in each of their sessions so you should not rely on them to be consistent.
If you want a consistent format then wrap the date/timestamp in TO_CHAR to apply that consistent format.
You are converting your string into a date or timestamp, and adjusting it by a day. Your client then decides how to format that for display, usually using you session setting like NLS_DATE_FORMAT.
If you want to display (or store*) the value in a particular format then you should specify that, with to_char(), e.g.:
TO_CHAR(TO_DATE(col1,'MM/DD/YYYY HH24:MI') + INTERVAL '1' DAY,'MM/DD/YYYY HH24:MI')
09/28/0021 18:05
or if you want to suppress some leading zeros to match your original string you can toggle those with the FM modifier:
TO_CHAR(TO_DATE(col1,'MM/DD/YYYY HH24:MI') + INTERVAL '1' DAY,'FMMM/DD/YYYY HH24:FMMI')
9/28/21 18:05
As you can see in the output of first of those, and as #Aitor mentioned, the year comes out as 0021 rather than 21. That's because you used a four-digit YYYY mask for a 2-digit year value. In the second one the FM suppresses that, so it's less obvious. As you don't seem to care about the century it usually doesn't matter whether you use YY or RR - the exception maybe being if you happen to hit a leap year/day; but it's still better to have the mask match the string, so with RR:
TO_CHAR(TO_DATE(col1,'MM/DD/RR HH24:MI') + INTERVAL '1' DAY,'FMMM/DD/RR HH24:FMMI')
9/28/21 18:05
db<>fiddle
* But you should not be storing dates as strings. They should be stored as dates, and formatted as strings for display only. You shouldn't really be using 2-digit years any more either.
You said your column has this: 9/27/21, but you put a mask like YYYY. Be careful with that, because with YYYY, the year will be 21 BC...
Maybe you want RRRR in your date mask. RRRR means 2-digit years in the range 00 to 49 are assumed to be in the current century:
select to_char(to_date('9/27/2021 18:05','MM/DD/RRRR HH24:MI')+ INTERVAL '1' DAY,'MM/DD/YYYY HH24:MI') result
from dual;
Result: 09/28/2021 18:05
I don't know what is your output format, but anyway, if you want your date formatted like VARCHAR, try this. With your column, is something like that
select to_char(to_date(col1,'MM/DD/RRRR HH24:MI') + 1,'MM/DD/YYYY HH24:MI') result
from your_table;
Also you can use, instead of INTERVATL '1' DAY, a simple +1

Converting timestamp to date in Oracle 12c

I want to convert a given timestamp in such format: 2019-04-08 00:00:00.0 to a date in this format: 2019-04-08.
I have already tried using:
SELECT TO_DATE('2019-04-20 00:00:00.0','YYYY-MM-DD') from dual;
But I got prompted with:
ORA-01830: date format picture ends before converting entire input
string
I think you may have some conceptual misunderstanding about how the TO_DATE function works, and also about how dates are processed by the DBMS.
YYY-MM-DD does not match the format of the actual string you're importing (2019-04-20 00:00:00.0) That's what the error is telling you. You must tell the TO_DATE function what to expect in the date string you input into it. You do that by means of the format string. if you don't specify a format string which matches the format you're actually going to supply, then the function will fail to process the string.
Next, you say you want to convert it "to a date in this format"...but this does not entirely make sense. TO_DATE converts a string into a variable of type DATETIME - i.e. a date object. A date object does not not exist in any particular format, it exists as an object. Internally it will store the date information in a way which is independent of any human-readable date format. The format relates entirely to the presentation of the date when seen as a string. Once you have a date object, you can then output the date in a particular format if you want to a human to be able to read it in the style that their culture is familiar with.
So, firstly to import your date string correctly as a date object, you can use an accurate format string, an also use TO_TIMESTAMP instead of TO_DATE so that it captures the sub-seconds value:
SELECT TO_TIMESTAMP('2019-04-20 00:00:00.0','YYYY-MM-DD HH24:MI:SS.FF5') from dual;
If you run this in a console the SELECT will then automatically re-format that date object (the result of the TO_DATE function) into the default date format configured in your server / session.
However if you actually want to see it on screen in a particular format, you can explicitly say so - a sensible way is using the TO_CHAR function:
SELECT TO_CHAR(TO_TIMESTAMPT('2019-04-20 00:00:00.0','YYYY-MM-DD HH24:MI:SS.FF5'), 'YYYY-MM-DD') from dual;
The full list of format specifiers can be found here (and in other places online as well).
Live demo of the above here: https://dbfiddle.uk/?rdbms=oracle_18&fiddle=619d918ea73953e11b3150c6b560112c
Assuming the input is actual text, and not a real timestamp, you could try just truncating the text before you call TO_DATE:
WITH cte AS (
SELECT '2019-04-20 00:00:00.0' AS ts FROM dual
)
SELECT TO_DATE(SUBSTR(ts, 1, 10), 'YYYY-MM-DD')
FROM cte;
If your input is an actual Oracle timestamp, and you want to convert it to a date, then you may use CAST:
SELECT CAST(ts AS DATE) dt
FROM cte;
Would CAST do any good?
I'm setting date format so that it displays time component, although it is 00:00:
SQL> alter session set nls_date_format = 'dd.mm.yyyy hh24:mi:ss';
Session altered.
SQL> select cast(timestamp '2019-04-20 00:00:00.0' as date) result from dual;
RESULT
-------------------
20.04.2019 00:00:00
Another format (without time component):
SQL> alter session set nls_date_format = 'dd.mm.yyyy';
Session altered.
SQL> select cast(timestamp '2019-04-20 00:00:00.0' as date) result from dual;
RESULT
----------
20.04.2019
SQL>
Or, using TO_CHAR function (so that session's date format doesn't matter):
SQL> select to_char(timestamp '2019-04-20 00:00:00.0', 'dd.mm.yyyy') result from dual;
RESULT
----------
20.04.2019
SQL>

What is Oracle's Default Date Format?

I have an Oracle DB, and I don't control the date format. I want to know what the date format is to ensure that searches like
select * from search where search_date>='03/16/2016 00:00:00'
work as expected.
Don't do that - you are relying on implicit data type conversion which is going to fail at some point.
You have two options:
1) Use a proper ANSI SQL date literal:
select *
from search
where search_date >= timestamp '2016-03-16 00:00:00';
2) use to_date() (or to_timestamp()) and use a custom format.
select *
from search
where search_date >= to_date('03/16/2016 00:00:00', 'mm/dd/yyyy hh24:mi:ss');
With to_date() you should avoid any format that is language dependent. Use numbers for the month, not abbreviations (e.g. 'Mar' or 'Apr') because they again rely on the client language.
More details can be found in the manual: https://docs.oracle.com/cd/E11882_01/server.112/e41084/sql_elements003.htm#SQLRF51062
Never rely on implicit data type conversion.
You can get all the NLS session parameters with the query:
SELECT * FROM NLS_SESSION_PARAMETERS;
or, if you have the permissions GRANT SELECT ON V_$PARAMETER TO YOUR_USERNAME;, you can use the command:
SHOW PARAMETER NLS;
If you just want the date format then you can do either:
SELECT * FROM NLS_SESSION_PARAMETERS WHERE PARAMETER = 'NLS_DATE_FORMAT';
or
SHOW PARAMETER NLS_DATE_FORMAT;
However, you could also use ANSI date (or timestamp) literals which are format agnostic. An ANSI date literal has the format DATE 'YYYY-MM-DD' and a timestamp literal has the format TIMESTAMP 'YYYY-MM-DD HH24:MI:SS.FF9'. So your query would be:
select * from search where search_date>= DATE '2016-03-16'
or
select * from search where search_date>= TIMESTAMP '2016-03-16 00:00:00'
What is Oracle's Default Date Format?
A DATE doesn't have any format. Oracle does not store dates in the format you see. It stores it internally in 7 bytes with each byte storing different components of the datetime value.
Byte Description
---- -------------------------------------------------
1 Century value but before storing it add 100 to it
2 Year and 100 is added to it before storing
3 Month
4 Day of the month
5 Hours but add 1 before storing it
6 Minutes but add 1 before storing it
7 Seconds but add 1 before storing it
To display, use TO_CHAR with proper FORMAT MODEL.
For comparing, use TO_DATE with proper FORMAT MODEL.
What you see as a format by default, is your locale specific NLS settings.
SQL> select parameter, value from v$nls_parameters where parameter='NLS_DATE_FORMAT';
PARAMETER VALUE
--------------- ----------------------------------------------------------------
NLS_DATE_FORMAT DD-MON-RR
SQL> select sysdate from dual;
SYSDATE
---------
17-MAR-16
SQL> select to_char(sysdate, 'mm/dd/yyyy hh24:mi:ss') from dual;
TO_CHAR(SYSDATE,'MM
-------------------
03/17/2016 12:48:41
SQL>
search_date>='03/16/2016 00:00:00'
You are comparing a DATE with a string literal. Always, explicitly convert the string into date using TO_DATE and proper format mask.
TO_DATE('03/16/2016', 'MM/DD/YYYY')
Or, if you dealing only with the date part and not concerned with the time portion, then use the ANSI date literal which uses a fixed format DATE 'YYYY-MM-DD'
DATE '2016-03-16'
You might just be lucky to get an output due to an implicit datatype conversion based on your locale specific NLS settings. Never ever rely on implicit datatype conversion, it might work for you, might fail for others where the nls settings are different.

Formatting value of year from SYSDATE

I want to insert the current date into one of the columns of my table. I am using the following:
to_date(SYSDATE, 'yyyy-mm-dd'));
This is working great, but it is displaying the year as '0014'. Is there some way that I can get the year to display as '2014'?
Inserting it as TRUNC(sysdate) would do. Date actually doesn't have a format internally as it is DataType itself. TRUNC() actualy will just trim the time element in the current date time and return today's date with time as 00:00:00
To explain what happened in your case.
say ur NLS_DATE_FORMAT="YY-MM-DD"
The Processing will be like below
select to_date(to_char(sysdate,'YY-MM-DD'),'YYYY-MM-DD') from dual;
Output:
TO_DATE(TO_CHAR(SYSDATE,'YY-MM-DD'),'YYYY-MM-DD')
January, 22 0014 00:00:00+0000
2014 - gets reduced to '14' in first to_char() and later while converted again as YYYY.. it wil be treated as 0014 as the current century detail is last!
to_date is used to convert a string to a date ... try to_char(SYSDATE, 'yyyy-mm-dd') to convert a date to a string.
The to_date function converts a string to a date. SYSDATE is already a date, so what this will do is to first convert SYSDATE to a string, using the session's date format as specified by NLS settings, and then convert that string back to date, using your specified date format (yyyy-mm-dd). That may or may not give correct results, depending on the session's NLS date settings.
The simple and correct solution is to skip the to_date from this and use SYSDATE directly.
Try this to_date(SYSDATE, 'dd-mm-yy')

Perl and Oracle DB - help

I am using Oracle express database, and I would like to know how can I change the date formatting-
from dd-mm-yyyy to dd-mm-yyyy hh-mm. Also, I've heard something about alter session, but I don't know how to use it in Perl.
This is what I did so far:
my $sth = $dbh->prepare("INSERT INTO Perl
(A_FIELD,B_FIELD,C_FIELD,TIME_STAME)
VALUES
(?,?,?,TO_DATE(?,'DD/MM/YYYY HH24:MI'))");
Date fields in Oracle are not formatted for display - it's an internal format that you convert to/from on input/output. When you store a date in Oracle date datatype columns, you convert your character string to internal format by describing the date-time to the TO_DATE function with the format model string. Oracle interprets the character string to it's internal format. When you need to display the date, you do the reverse - you tell oracle how to display the date by again giving a format model, this time to the TO_CHAR function.
To illustrate with your example, you could convert dd-mm-yyyy to dd-mm-yyyy hh-mm without ever storing the value (I assume you meant to display hours-minutes. The format model for minutes is 'MI', since 'MM' is month):
SQL> SELECT TO_CHAR(TO_DATE('01-01-2020','DD-MM-YYYY'),'DD-MM-YYYY HH-MI') mydate
FROM DUAL;
MYDATE
----------------
01-01-2020 12-00
Note that with your example, the time portion of your date is not supplied on input, so it defaults to midnight. To store a time value in your date column, you must supply a time value in your input:
SQL> SELECT TO_CHAR(TO_DATE('01/01/2020 10:13','DD/MM/YYYY HH:MI'),'DD-MM-YYYY HH-MI') mydate
FROM DUAL;
MYDATE
----------------
01-01-2020 10-13
SQL>
Depending on what you're trying to do, the system date in Oracle can be obtained by a reference to the pseudo-column SYSDATE:
SQL> SELECT TO_CHAR(sysdate,'MM/DD/YYYY HH:MI:SS AM') dt1,
2 TO_CHAR(sysdate,'DD-MON-YYYY HH24:MI:SS') dt2
3 FROM dual;
DT1 DT2
---------------------- -----------------------------
07/01/2011 03:44:30 PM 01-JUL-2011 15:44:30
SQL>
So the roundabout answer to your question is that it entirely depends on what format your input date string is in. You convert that to Oracle's date type via a format model and the TO_DATE function, then convert the date item to a display format of your choosing via TO_CHAR and a format model. As for the "ALTER SESSION" command you alluded to in your question, you can specify a default format model for date conversions by specifying the NLS_DATE_FORMAT parameter in the ALTER SESSION command:
SQL> SELECT sysdate FROM dual;
SYSDATE
---------
02-JUL-11
SQL> ALTER SESSION SET nls_date_format='dd-mon-yyyy hh24:mi:ss';
Session altered.
SQL> SELECT sysdate FROM dual;
SYSDATE
--------------------
02-jul-2011 10:39:24
If the incoming date string is in mm-yyyy format, then you can use the statement below(TO_DATE(?,'MM-YYYY')) to convert the string to date:
$sth = $dbh->prepare("INSERT INTO Perl (A_FIELD,B_FIELD,C_FIELD,TIME_STAME) VALUES (?,?,?,TO_DATE(?,'MM-YYYY'))");