SQLPLus vs SQLDeveloper behavior - oracle

I'm experiencing a different behavior between SQLPlus and SQL Developer.
Example data:
create table test (
INIT_DATE DATE
);
INSERT INTO test(INIT_DATE) values (sysdate);
COMMIT;
Now I run the following query (notice we're doing an unnecessary to_date because INIT_DATE is already a date):
select to_date(INIT_DATE, 'dd/mm/rrrr') from test;
The result is:
SQLPlus => Return 20/09/16
SQLDeveloper => Throw ORA-01861
I found this answer, so in SQLDeveloper I changed NLS>Format Date to 'DD/MM/RR' and now SQLDeveloper return 20/09/16.
But, if in SQLDeveloper I change NLS to 'DD/MM/RR HH24:MI:SS' again, and I change the query mask to 'DD/MM/RR', SQLDeveloper return an error again:
select to_date(INIT_DATE, 'DD/MM/RR') from test;
Can anyone explain this behavior?
Why SQLDeveloper throw an error if the query mask is 'DD/MM/RR' but not when NLS is 'DD/MM/RR'?

Use TO_CHAR instead of TO_DATE. TO_DATE function converts char argument in specific format given by second parameter to date value.
Your statement
select to_date(INIT_DATE, 'DD/MM/RR') from test;
does first implicit conversion to char, because INIT_DATE is a date. This conversion is in nls default format, depending on your machine settings.

You try convert DATE to DATE through TO_DATE function, but TO_DATE function arguments are strings and as result Oracle convert INIT_DATE column to string and then pass this string into TO_DATE function.
If you use implicit conversion 'string to date' or 'date to string' , then Oracle use the default date format. In different environments default date format may be different.
Try to use an explicit conversion and an appropriate format.
For example:
select to_date(to_char(INIT_DATE, 'dd/mm/rrrr'), 'dd/mm/rrrr') from test;

Related

Getting error while running session as not avalid month

I have a oracle view in which we have column called dayofset which defined from subtraction of two date columns like(to_date(date_column1)-to_date(date_column2)) and it is stored as number(38) datatype.
2.so,when I run session in informatica to get data from oracle view to redshift.im getting error like "not a valid month".
3.Input values for that column is like (25-JAN-21,10-APR-13)
4.im getting the output values like 1,2,3,4... Like this all are integer values.(this column just do the datediff operation) and provide the difference between two dates.
Could you guys please help on this.
I have a oracle view in which we have column called dayofset which defined from subtraction of two date columns like to_date(date_column1)-to_date(date_column2) and it is stored as number(38) datatype.
Never use TO_DATE on a column that is already a DATE data type. Just use.
CREATE VIEW your_view (dayofset)
SELECT date_column1 - date_column2
FROM your_table;
If you use TO_DATE then it takes a string as the first argument so you are effectively performing an implicit conversion to a string to convert it back to a date and your code is the equivalent of:
CREATE VIEW your_view (dayofset)
SELECT TO_DATE(
TO_CHAR(
date_column1,
(SELECT value FROM NLS_SESSION_PARAMETERS WHERE parameter = 'NLS_DATE_FORMAT')
),
(SELECT value FROM NLS_SESSION_PARAMETERS WHERE parameter = 'NLS_DATE_FORMAT')
)
-
TO_DATE(
TO_CHAR(
date_column2,
(SELECT value FROM NLS_SESSION_PARAMETERS WHERE parameter = 'NLS_DATE_FORMAT')
),
(SELECT value FROM NLS_SESSION_PARAMETERS WHERE parameter = 'NLS_DATE_FORMAT')
)
FROM your_table;
Depending on your NLS_DATE_FORMAT session parameter, this could just be a waste of time or it could truncate the date and give you an unexpected result; however, any user can change their session parameters at any time so you may get different results for different users so you should NEVER rely on implicit conversions.
If your columns are not a DATE data-type but are strings then use an explicit format model (and, if required, language) in the conversion:
CREATE VIEW your_view (dayofset)
SELECT TO_DATE(string_column1, 'DD-MON-RR', 'NLS_DATE_LANGUAGE=English')
- TO_DATE(string_column2, 'DD-MON-RR', 'NLS_DATE_LANGUAGE=English')
FROM your_table;

how can we change one date format to another format in oracle sql? ORA-01861

How can we change the date format from DD-MON-YYYY to this format YYYY-MM-DD.
I have a date type column in a table. I want to display that value of that date column in this format - YYYY-MM-DD.
I tried with this -
disp_date := to_char(to_date(disp_date,'dd-mm-rrrr'),'rrrr-mm-dd')
and
disp_date := to_char(to_date(disp_date,'dd-mm-yyyy'),'yyyy-mm-dd')
While executing the above I got an error message stating that:
ORA-01861 Literal does not match format string
Please note the below details of my system,
select value from v$nls_parameters where parameter = 'NLS_DATE_LANGUAGE';
--AMERICAN
select value from v$nls_parameters where parameter = 'NLS_DATE_FORMAT';
--DD-MON-RRRR
If column's datatype is DATE - which is what your sentence suggests:
I have a date type column in a table
then you don't to_date it - it already is a date. Just apply to_char with desired format mask, e.g.
select to_char(disp_date, 'yyyy-mm-dd') from your_table
If you want to change the default display format then run
alter session set nls_date_format = 'YYYY-MM-DD';
select disp_date from ...
Note, your client application may change the format again according to settings in this client application.
A date does not have a format - it is stored internally to the database as a binary value using 7-bytes (representing century, year-of-century, month, day, hour, minute and second). It is not until whatever user interface you are using (i.e. SQL/Plus, SQL Developer, Java, etc.) tries to display it to you, the user, that is is converted it into something you would find meaningful (usually a string) that the date is formatted (and that conversion is done by the user interface and not by the database).
How can we change one date format to another format in oracle?
Since a date does not have a format then this question does not make sense.
If instead, you ask:
How can we display a date in a format in oracle?
If you want to display the date with a specific format then you want to explicitly convert it from a date to a string using TO_CHAR (rather than relying on an implicit conversion by the user interface). Since it is already a DATE then you do not need to use TO_DATE on it and can just use:
DECLARE
date_value DATE := SYSDATE;
formatted_date VARCHAR2(10);
BEGIN
formatted_date := TO_CHAR(date_value, 'yyyy-mm-dd');
DBMS_OUTPUT.PUT_LINE( formatted_date );
END;
/
Now, if your disp_date variable is a string (and not a date) then your code works:
DECLARE
disp_date VARCHAR2(11) := TO_CHAR(SYSDATE, 'DD-MON-RRRR');
BEGIN
disp_date := TO_CHAR(TO_DATE(disp_date, 'DD-MON-RRRR'), 'yyyy-mm-dd');
DBMS_OUTPUT.PUT_LINE( disp_date );
END;
/
db<>fiddle here

changing Date format in query

in some part of my program , I want to run a sql query and have the result which is a date like : %Y/%m/%d %H:%M:%S
SELECT MAX(created_at)
FROM HOT_FILES_LOGS
WHERE FILE_NAME = 'test'
date in created_at column is stored like 04/03/2021 15:45:30 ( it is fulled with SYSDATE)
but when I run this query, I get just 04.03.21
what should I do to fix it?
Apply TO_CHAR with appropriate format mask:
select to_char(max(created_at), 'yyyy.mm.dd hh24:mi:ss') as created_at
from hot_files_logs
where file_name = 'test'
Oracle does not store dates or timestamps in any display format, they are stored in an internal structure, every date in every Oracle database since at least 8i and probably earlier. This structure consists of 7 1-byte integers (timestamps in a similar but larger structure). How the date is displayed or a string converted to a date is controlled the specified date format string in the to_char or to_date function or if no format string given by the NLS_DISPLAY_FORMAT setting. To get a gimps at the internal settings run the following:
create table td( d date);
insert into td(d) values(sysdate);
select d "The Date" , dump(d) "Stored As" from td;
See example. The last used format is not practical but strictly demonstrable. Well I guess you could use it to seed a repeatable random sequence.

extract month and year in oracle

Why does below query work successfully?
select to_char(sysdate,'MM-YYYY') from dual;
But the following queries give an invalid number error:
select to_char('28-JUL-17','MM-YYYY') from dual;
select to_char('7/28/2017','MM-YYYY') from dual;
Though, below query gives you the same date format.
select sysdate from dual; -- 7/28/2017 11:29:01 AM
TO_CHAR function accepts only date or number. Maybe you can try this
select to_char(to_date('28-JUL-17', 'DD-MON-YY'),'MM-YYYY') from dual;
As a side note, if you're planning to convert a bunch of dates to strings so you can look for all records in a certain month of a certain year, be aware that the TRUNC function can be used to reduce the precision of a date (e.g. to "month and year"). The following query pulls all records created this month, from the table. It should be faster than converting dates to char and doing string comparison..
SELECT * FROM table WHERE trunc(create_date, 'MON') = trunc(sysdate, 'MON')
Because function TO_CHAR() accepts date or timestamp values. However, neither '28-JUL-17' nor '7/28/2017' are dates or timestamps - they are STRINGS.
Oracle gently tries to convert these stings into DATE values. This implicit conversion may work or may fail, it depends on your current session NLS_DATE_FORMAT, resp. NLS_TIMESTAMP_FORMAT settings.
As given already in other answers you have to convert the string explicitly:
TO_DATE('28-JUL-17', 'DD-MON-RR')
TO_DATE('7/28/2017', 'MM/DD/YYYY')
to_char() isn't expecting you to start with a char value. If you really want that to work, you'll need to wrap it around a to_date() function.
to_char(
to_date(
'28-JUL-17'
, 'DD-Mon-YY'
)
,'MM-YYYY'
)
You are using an incorrect mask, for more information read here.
The correct one should be:
select to_char(to_date('28-JUL-17','DD-MON-YY'), 'MON-YY') from dual;
You can also extract the month using EXTRACT:
select EXTRACT (MONTH FROM to_date('28-JUL-17','DD-MON-YY')) from dual;
Cheers

TO_DATE function in ORACLE

I was trying the TO_DATE function. Specifically, I noted that the following queries
1. SELECT TO_CHAR(TO_DATE('01-01-2015','DD-MM-YYYY'),'DD-MON-YY') FROM DUAL
2. SELECT TO_DATE('01-01-2015','DD-MM-YYYY') FROM DUAL
have the same output: 01-JAN-2015.
Why does the TO_DATE function return the month in its abbreviated form?
My expected output for the second query is something like 01-01-2015 (simply, a TYPE conversion, NOT a format conversion).
Am I wrong?
Thanks
Dates do not have a format - they are represented by 7- or 8-bytes.
SELECT DUMP( SYSDATE ) FROM DUAL;
Might output:
Typ=13 Len=8: 220,7,11,26,16,41,9,0
This format is very useful for computers to compare dates but not so useful to people; so, when the SQL client (SQL/plus, SQL Developers, TOAD, etc) displays a date it does not display the the bytes but displays it as a string.
It does this by making an implicit call to TO_CHAR() (or some other internal method of stringifying dates) and uses a default format mask to perform this conversion.
SQL/Plus and SQL Developer will use the user's session parameter NLS_DATE_FORMAT to perform this conversion - see this answer regarding this.
So your second query is implicitly being converted to do something approaching this (but, almost certainly, more efficiently):
SELECT TO_CHAR(
TO_DATE('01-01-2015','DD-MM-YYYY'),
( SELECT VALUE FROM NLS_SESSION_PARAMETERS WHERE PARAMETER = 'NLS_DATE_FORMAT' )
)
FROM DUAL
The default output format of DATE value, resp TO_DATE() function is set by NLS_DATE_FORMAT value. You can verify it with this query:
SELECT *
FROM V$NLS_PARAMETERS
WHERE PARAMETER = NLS_DATE_FORMAT';
You can change it on session level for example with
alter session set NLS_DATE_FORMAT = 'DD-MM-YYYY';
The output format of TO_CHAR is not correct, try:
SELECT TO_CHAR(TO_DATE('01-01-2015','DD-MM-YYYY'),'DD-MM-YYYY') FROM DUAL;
Oracle TO_DATE: is used to convert a character string to a date format.
and related to your concern; you need to alter your session like below:
alter session set nls_date_format='DD-MM-YYYY'
in your apps right after the connect.
So now if you run again your query :
SELECT TO_DATE ('01-01-2015', 'DD-MM-YYYY')
FROM DUAL;
the result would be as expected:
01-01-2015
Hope that will help.

Resources