WHAT IS WRONG THIS QUERY? [closed] - sql

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 7 days ago.
Improve this question
SELECT MONTHS_BETWEEN(LAST_DAY('15-JAN-12') + 1, '01-APR-12')
FROM DUAL;
ERROR : not a valid month

Never rely on implicit date conversions.
'15-JAN-12' is not a date; it is a string literal that happens to look like a date. Oracle will try to be helpful and will try to convert the string to a date and will implicitly convert your query to the equivalent of:
SELECT MONTHS_BETWEEN(
LAST_DAY(
TO_DATE(
'15-JAN-12',
(SELECT value FROM NLS_SESSION_PARAMETERS WHERE parameter = 'NLS_DATE_FORMAT')
)
) + 1,
TO_DATE(
'01-APR-12',
(SELECT value FROM NLS_SESSION_PARAMETERS WHERE parameter = 'NLS_DATE_FORMAT')
)
)
FROM DUAL;
Which may give you the correct answer if the NLS_DATE_FORMAT is DD-MON-RR.
However, if you use:
ALTER SESSION SET NLS_DATE_FORMAT = 'fxDD-MM-YYYY';
Then the same query outputs:
ORA-01858: a non-numeric character was found where a numeric was expected
and if you use:
ALTER SESSION SET NLS_DATE_FORMAT = 'YYYY-MM-DD HH24:MI:SS';
then it is even worse, the query doesn't fail it outputs the unexpected value 165.6451612903226.
Always specify a format model.
What you should do is not rely on implicit conversions and always use explicit conversion (and, if you are using a specific language then specify the language as well):
SELECT MONTHS_BETWEEN(
LAST_DAY(
TO_DATE('15-JAN-12', 'DD-MON-RR', 'NLS_DATE_LANGUAGE=English')
) + 1,
TO_DATE('01-APR-12', 'DD-MON-RR', 'NLS_DATE_LANGUAGE=English')
)
FROM DUAL;
Or, you can use a date literal:
SELECT MONTHS_BETWEEN(
LAST_DAY(
DATE '2012-01-15'
) + 1,
DATE '2012-04-01'
)
FROM DUAL;

You need to use the TO_DATE() function to convert a string to a date literal.
SELECT MONTHS_BETWEEN(LAST_DAY(TO_DATE('15-JAN-12', 'dd-mmm-yyy')) + 1, TO_DATE('01-APR-12', 'dd-mmm-yyy'))
FROM DUAL;
You can also use date literals, which are written as DATE 'YYYY-MM-DD'
SELECT MONTHS_BETWEEN(LAST_DAY(DATE '2012-01-15') + 1, DATE '2012-04-01')
FROM DUAL;
DEMO

Usually Oracle expects the month part to be written in full form (e.g. JANUARY, APRIL).
Try this: SELECT MONTHS_BETWEEN(LAST_DAY('15-JANUARY-12') + 1, '01-APRIL-12')
FROM DUAL;

Related

How do I convert a date to Shamsi/Persian format in Oracle SQL?

I want to convert date to Shamsi/Persian format, but it did not work well. My code:
SELECT TO_CHAR('10-JUN-18', 'dd-mm-yy','nls_calendar=persian')
FROM dual;
I want it be like this: 20-03-97
TO_CHAR( date_value, format_model, nls_parameters ) takes a DATE data type as the first argument.
'10-JUN-18' is not a DATE data type; it is a string literal (that just happens to look like a date). Oracle will try to perform an implicit conversion from a string to a date but this implicit conversion is failing (and it is bad practice to rely on implicit conversions).
If you use a DATE literal then your code works:
SELECT TO_CHAR(DATE '2018-06-10', 'dd-mm-yy','nls_calendar=persian') AS dt
FROM DUAL;
DT
20-03-97
Or, you can explicitly convert the string literal to a date and then convert it back:
SELECT TO_CHAR(
TO_DATE('10-JUN-18', 'DD-MON-RR', 'NLS_DATE_LANGUAGE=English'),
'dd-mm-yy',
'nls_calendar=persian'
) AS dt
FROM DUAL;
DT
20-03-97
db<>fiddle here

How can I do a query that return ’01-JAN-1900’

We are using Oracle 11.
Both below queries return 01-JAN-00
SELECT to_date('01-JAN-1900','dd-MM-yyyy') FROM DUAL
SELECT to_date('01-JAN-1900','dd-MM-RRRR') FROM DUAL
How can I do a query that return ’01-JAN-1900’ ?
I need to do the below query (myDtColumn is a Date column), if I just use '01-JAN-1900' without the to_date, I will get an error 'inconsistent data types: expected %s got %s'
case when myDtColumn is null then to_date('01-JAN-1900','dd-MM-yyyy') else
myDtColumn end as myDt
When I try the below, I am still getting '01-JAN-00' instead of '01-JAN-1900'
case when myDtColumn is null then DATE '1900-01-01' else
myDtColumn end as myDt
Dates do not have a format - they are represented internally by 7 or 8 bytes. If you want a date to have a format then you will need to convert it to a data type that can be formatted (i.e. a string). When the user interface you are using needs to display a date then it will implicitly convert it to a string and Oracle uses the NLS_DATE_FORMAT session parameter as its default format.
You can change this using:
ALTER SESSION SET NLS_DATE_FORMAT = 'DD-MON-YYYY';
Then either of your queries or, using a date literal:
SELECT DATE '1900-01-01' FROM DUAL
Will be implicitly formatted using the NLS_DATE_FORMAT when the UI displays them.
Or for your query:
SELECT COALESCE( myDtColumn, DATE '1900-01-01' ) as myDt
FROM your_table;
If you do not want to change the session parameters then use TO_CHAR( date_value, 'DD-MON-YYYY' ):
SELECT TO_CHAR( COALESCE( myDtColumn, DATE '1900-01-01' ), 'DD-MON-YYYY' ) as myDt
FROM your_table;

how to get the date format in 'DD-MM-YY' format in ORACLE without using TO_CHAR?

How do we convert a date in the 'DD-MM-YY' format WITHOUT using to_char ?
If I use the following query i get it in DD-Mon-YY format ?
select TO_DATE(SYSDATE,'DD-MM-YY') from dual ;
Output : 29-Mar-18
I want it in 29-03-18 format , without using to_char.
Is it possible ?
How do we convert a date in the 'DD-MM-YY' format WITHOUT using to_char ?
This is a common misconception that dates in the database have a format.
A date does not have a format - it is stored internally to the database as 7-bytes (representing year, month, day, hour, minute and second) and 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, and converts it into something you would find meaningful (usually a string) that the date is given a format so that you, the user, find it meaningful on the client software.
So the question you should be asking is:
How do we get <insert name of SQL client software here> to change the default format it uses for a DATE data type?
If you are using SQL/Plus or SQL Developer then it will use the NLS_DATE_FORMAT session parameter to format the date. You can change this using:
ALTER SESSION SET NLS_DATE_FORMAT = 'DD-MM-YY';
Note: This is a session parameter and will only change the format for the current session (not for any other users or any subsequent sessions).
If you want to set this as the session default then you could set a logon trigger (if users are relying on the previous default format then applying this may not be well received).
You can also change the preferences in the SQL Developer GUI as described here.
we dont have alter permission , its client db
Then use TO_CHAR( date, format_model ) - that is what it is there for.
Note: Please do not use 2-digit years as the expected format. It is a source of errors when dates are given an unexpected and wrong century.
If I use the following query i get it in DD-Mon-YY format ?
select TO_DATE(SYSDATE,'DD-MM-YY') from dual ;
TO_DATE( date_string, format_model ) takes two string arguments and Oracle will implicitly call TO_CHAR to convert your date to a string so it will match the expected data type and then when the client program formats it it will implicitly perform a similar transformation again. So your query is effectively:
SELECT TO_CHAR(
TO_DATE(
TO_CHAR(
SYSDATE,
( SELECT VALUE
FROM NLS_SESSION_PARAMETERS
WHERE PARAMETER = 'NLS_DATE_FORMAT'
)
),
'DD-MM-YY'
),
( SELECT VALUE
FROM NLS_SESSION_PARAMETERS
WHERE PARAMETER = 'NLS_DATE_FORMAT'
)
)
FROM DUAL;
If the NLS_DATE_FORMAT is MM-DD-YY then SYSDATE will be implicitly converted to the default MM-DD-YY format then explicitly converted to a date using your format DD-MM-YY, and the day/month values will be swapped, before being converted back to the default MM-DD-YY format for display. Relying on implicit conversions is prone to many errors - try to avoid it.
If you want a date for your SQL client to format using their default format then just use:
SELECT SYSDATE FROM DUAL;
If you want to get a formatted date then use TO_CHAR( date, format_model ):
SELECT TO_CHAR( SYSDATE, 'DD-MM-YY' ) FROM DUAL;
ALTER SESSION is one option:
SQL> alter session set nls_date_format = 'dd-mm-yy';
Session altered.
SQL> select sysdate from dual;
SYSDATE
--------
29-03-18
Note that what you did - applied TO_DATE function to SYSDATE - is wrong. SYSDATE already returns DATE, so you could have applied TO_CHAR to it (with appropriate format mask), but not TO_DATE.
I would suggest you to use TO_CHAR or nls_date_format , though EXTRACT is an alternative if you want to answer an interview question.
SELECT EXTRACT (DAY FROM SYSDATE)
||'-'
|| LPAD(EXTRACT (MONTH FROM SYSDATE), 2, 0)
|| '-'
|| SUBSTR( EXTRACT(YEAR FROM SYSDATE),-2) as dt
FROM DUAL;

Oracle SYSDATE format Change

I am trying to change a format of Oracle SYSDATE so that it uses a specific format when running a PL/SQL procedure. This format is really unnecessary but I am update an old table and need to maintain this format due to some integrations. My problem is I am not able to replicate the format.
The format needed is: 15/MAR/17 09:31:08.000000000
Currently the below is the closest I can get, I am not sure how to change MM to display MAR instead of 03.
SELECT TO_CHAR
(SYSDATE, 'DD/MM/YY HH24:MI:SS.SSSSSSSSS')
FROM DUAL;
Thanks a mill in advance
MON will display Month instead of numeric.
SELECT TO_CHAR
(SYSDATE, 'DD/MON/YY HH24:MI:SS."000000000"')
FROM DUAL;
SYSDATE is of DATE type, which does not support fractional seconds, so you either need to concatenate .000000000 with the formatted date:
SELECT TO_CHAR(
SYSDATE,
'DD/MM/YY HH24:MI:SS'
) || '.000000000'
FROM DUAL;
Or you need to CAST the DATE to a TIMESTAMP:
SELECT TO_CHAR(
CAST( SYSDATE AS TIMESTAMP ),
'DD/MM/YY HH24:MI:SS.FF9'
)
FROM DUAL;
To convert to text in the format you want (not that you should need to unless the DB design is awful).
substr(to_char(systimestamp,'DD/MON/YY HH24:MI:SS.FF') || '000000000', 1, 28)
or
to_char(sysdate,'DD/MON/YY HH24:MI:SS') || '.000000000'
Details on the format mask can be found here.
Note: sysdate does not return the fraction of a second, so if this is required, use systimestamp

Date conversion in Oracle not working as expected

ORACLE 10 g db: convert date format from
02-JUL-14
to
02/JUL/14
I tried using the the select query below to get "02/JUL/14" instead it shows "02-JUL-14":
SELECT ROUTINGNUM , to_date (EFFDATE,'DD/MM/YYYY') FROM hat;
Can anybody please help reading this.
if EFFDATE is a date column,
SELECT ROUTINGNUM , to_char( EFFDATE,'DD/MON/YYYY') FROM hat;
if it is a String in the format DD-MON-YY
SELECT ROUTINGNUM , to_char( to_date( EFFDATE,'DD-MON-YY') ,'DD/MON/YYYY')
FROM hat;
TO_DATE function is used for converting from String to Date type. Use TO_CHAR function instead.
If your EFFDATE field is already a date type, then you just need to change NLS_DATE_FORMAT.
alter session set NLS_DATE_FORMAT = 'DD/MM/YYYY';
select eff_date from hat;
Or use TO_CHAR on EFFDATE
select to_char(eff_date, 'DD/MM/YYYY') from hat;
If you typically deal with a certain format of date, then you can change the default for your instance by setting one or more of the NLS init parameters.
sqlplus / as sysdba
show parameter nls