Unable to convert varchar2 to Date in oracle - sql

I am trying to convert one of the varchar2 column to date in oracle using the below query.
SELECT *
FROM login
WHERE to_date(END_DATE,'DD-MM-YY') < to_date(TRUNC(SYSDATE)-90,'DD-MM-YY');
I am converting the both side to date with a common formatter. But still I am getting the below error while executing this query.
ORA-01861: literal does not match format string
01861. 00000 - "literal does not match format string"
*Cause: Literals in the input must be the same length as literals in
the format string (with the exception of leading whitespace). If the
"FX" modifier has been toggled on, the literal must match exactly,
with no extra whitespace.
*Action: Correct the format string to match the literal
Can you please help me to sort out this problem?

to_date(END_DATE,'DD-MM-YY')
First of all, it is a bad design to store DATE as STRING. Date should always be stored as DATE data type, there is no reason to store it as characters.
If your data is stored as 14-Mar-2015 then why are you using the 'DD-MM-YY' format. Clearly the formats doesn't match. You should use proper format model.
For example,
TO_DATE(14-Mar-2015,'DD-Mon-YYYY','NLS_DATE_LANGUAGE=ENGLISH')
to_date(TRUNC(SYSDATE)-90,'DD-MM-YY')
This makes no sense. TRUNC on DATE would return you DATE after truncating the time portion.
Never ever use TO_DATE on DATE. It will implicitly convert it into string and then back to date using locale-specific NLS format. See a detailed explanation in my previous answer here https://stackoverflow.com/a/29559609/3989608
Your modified query would look like:
SELECT *
FROM login
WHERE to_date(END_DATE,'DD-Mon-YYYY','NLS_DATE_LANGUAGE=ENGLISH') < TRUNC(SYSDATE)-90;

Related

Oracle SQl- How to Convert T00:00:00 into AM or PM readable time in Oracle SQL

I tried to convert via:
TO_TIMESTAMP ("T00:00:00", '"T"hh:mi:ss')
It displayed error>>
ORA-01861: literal does not match format string
01861. 00000 - "literal does not match format string"
*Cause: Literals in the input must be the same length as literals in
the format string (with the exception of leading whitespace). If the
"FX" modifier has been toggled on, the literal must match exactly,
with no extra whitespace.
*Action: Correct the format string to match the literal.
Your immediate issue is with hh: this stands for a 12-hour based format (am/pm), so it allows values between 1 and 12 only (0 is not a valid hour in 12-hour format).
You also should not be using double quotes around the literal string ; but I don't think you are actually doing that in your code, otherwise you would get error invalid identifier.
Then: there is no time datatype in Oracle anyway - just date (which, couter-intuitively enough, includes a time portion), and various flavors of timestamps. If you are looking to convert the input string to a string that represents a time in AM/PM format, then you can do something like this:
to_char(to_date('T00:00:00', '"T"hh24:mi:ss'), 'hh12:mi:ss am')
This turns the time string to a date (the date part defaults to the current date when not specified), then returns its time portion format in am/pm format. This yields:
12:00:00 AM

format date in oracle SQL

I was trying to learn how to format date in oracle pl oracle, when I ran below query its returns error
SELECT TO_DATE('01-JAN-00', 'YYYY-DD-MM') FROM dual;
the error message is
ORA-01858: a non-numeric character was found where a numeric was expected
01858. 00000 - "a non-numeric character was found where a numeric was expected"
*Cause: The input data to be converted using a date format model was
incorrect. The input data did not contain a number where a number was
required by the format model.
*Action: Fix the input data or the date format model to make sure the
elements match in number and type. Then retry the operation.
You are either not using the correct format specifier, or not passing the correct string. You want:
SELECT TO_DATE('2000-01-01', 'YYYY-DD-MM') FROM DUAL;
Or:
SELECT TO_DATE('01-JAN-00', 'DD-MON-YY') FROM DUAL;
Or you can simply declare a DATE litteral:
SELECT DATE'2000-01-01' FROM DUAL;
for my scenario I had to use to_char which perfectly solve the formatting issue.
SELECT TO_CHAR('01-JAN-00', 'yyyy-DD-MM') FROM dual;

Change system date suggestions nedded

We have a new software package that allows the company to write SQL code to be place on Query portals. We have several reports we wish to code using the previous day as one of the selections. If a report is ran on MONDAY we want to automatically select the previous FRIDAY as the selection date, We have ORACLE SQL DEVELOPER 4.1. The code we are trying to use is listed below:
SELECT ALERT_CD,ALERT_KEY,CHG_DTM,
CASE
WHEN TO_CHAR(SYSDATE,'fmday')='sunday'
THEN SYSDATE-2
WHEN TO_CHAR(SYSDATE,'fmday')='monday'
THEN SYSDATE-3
ELSE SYSDATE-1
END "change"
FROM SG00400T
WHERE ALERT_CD='AUTO'
and CHG_DTM >= to_date('SYSDATE', 'mm/dd/yyyy')
The error we are receiving:
ORA-01858: a non-numeric character was found where a numeric was expected
01858. 00000 - "a non-numeric character was found where a numeric was expected"
*Cause: The input data to be converted using a date format model was
incorrect. The input data did not contain a number where a number was
required by the format model.
*Action: Fix the input data or the date format model to make sure the
elements match in number and type. Then retry the operation.
The CHG_DTM is a date/time field which could be part of the problem we do not full understand at this time.
Any help would be greatly appreciated.
The expression to_date('SYSDATE', 'mm/dd/yyyy') is are trying to convert the string constant 'SYSDATE' to a date - which can't work.
But you should never, ever call to_date() on a value that is already a date. That will first convert the date value to a varchar just to convert that varchar back to a date which it was to begin with.
So the to_date() function is wrong at that place to begin with. Most probably you want:
and CHG_DTM >= trunc(SYSDATE)

Why sysdate-'dd-mm-yyy' is not valid in-spite of internal conversion being possible?

'dd-mm-yy' being NLS_DATE_FORMAT it is implicitly converted to Date data type during comparison, insertion but why is not converted during a arithmetic operation.
sysdate>'01-01-17' //is valid
sysdate-'01-01-17' //is in valid
First I assumed the operators(+,-,..) are only for numeric data type. Later I got to know these operators are used even in Date Arithmetic and even operands with Datedata type are also valid.
"During arithmetic operations on and comparisons between character and noncharacter datatypes, Oracle converts from any character datatype to a numeric, date, or rowid, as appropriate" -
doc
Using to_date solves the issue. I am looking for the reason why it is not implicitly converted.
Forget implicit conversion. Just express your dates using explicit date literals:
sysdate > date '2017-01-01'
sysdate - date '2017-01-01'
The code is clearer and less ambiguous as well.
As to why Oracle doesn't do implicit conversion in the second case. Oracle doesn't know what type to expect. The second operand could be either a date or a number, so it doesn't know how to convert the string. In the first case, the comparison should be to a date.
Adding more detail on Gordon Lindoff's answer with an example.
During sysdate>'010117' as your comparing with a date '010117' surely should be date and is implicitly converted. Same going during insert.
But during sysdate-'010117' the system has the possibilities of converting it Number or Date, and it chooses to convert into Number. So 'dd-mm-yy' format is tried to convert into Number in this context.

SQL Date Format Conversion

I have a question regarding SQL dates.
The table I am working with has a date field in the following format: "22-SEP-08". The field is a date column.
I am trying to figure out how to output records from 1/1/2000 to present day.
The code below is not filtering the date field:
Select distinct entity.lt_date
from feed.entitytable entity
where entity.lt_date >= '2000-01-01'
Any help regarding this issue is much appreciated. Thanks!
Edit: I am using Oracle SQL Developer to write my code.
DATEs do not have "a format". Any format you see is applied by the application displaying the date value.
You can either change the configuration of SQL Developer to display dates in a different format, or you can use to_char() to format the date the way you want.
The reason your statement does not work, is most probably because of the implicit data type conversion that you are relying on.
'2000-01-01' is a string value, not a date. And the string is converted using the NLS settings of your session. Given the fact that you see dates displayed as DD-MON-YY means that that is the format that is used by the evil implicit data type conversion. You should supply date values always as real date literals.
There are two ways of specifying a real date literal. The first is ANSI SQL and simple uses the keyword DATE in front of an ISO formatted string:
where entity.lt_date >= DATE '2000-01-01'
Note the DATE keyword in front of the string, wich makes it a real date literal not a string expression.
The other option is to use to_date() to convert a character value into a date:
where entity.lt_date >= to_date('2000-01-01', 'yyyy-mm-dd');
More details about specifying date literals can be found in the manual:
Date literals
to_date function
My guess is the data type isn't a Date. Just in case its a char type, try to convert it using the Oracle TO_DATE() function. The Oracle documentation below should help you with parameters.
http://docs.oracle.com/cd/B19306_01/server.102/b14200/functions183.htm
An implicit datatype conversion bites once again.
You're right. The predicate is not doing the comparison you are expecting,
Oracle is performing an implicit datatype conversion, from DATE to VARCHAR, so that it can do a comparison to the string literal.
If lt_date column is DATE datatype, then Oracle is seeing your where clause:
where entity.lt_date >= '2000-01-01'
Oracle is actually seeing it as if it's written like this:
where TO_CHAR(entity.lt_date) >= '2000-01-01'
And that's where the "format" problem comes in. The column itself does not have a "format". Because the second argument to the TO_CHAR function is not supplied, Oracle is using the value of the NLS_DATE_FORMAT parameter (from your session). And that's probably set to DD-MON-YY. Which is why that's the "format" you're seeing when you a run a SELECT statement in SQL*Plus. Because the DATE value is (again) being run through a TO_CHAR function to get a string that can be displayed.
To get the "filtering" you want, don't do a comparison to a string literal. Instead, do the comparison to an expression that has DATE datatype.
You can use the Oracle TO_DATE function. And you don't want to rely on setting of NLS_DATE_FORMAT, explicitly specify the format model as the second argument to the function. For example:
DO THIS
where entity.lt_date >= TO_DATE('2000-01-01','YYYY-MM-DD')
DON'T DO THIS
It's also possible to specify the format model as the second argument to the TO_CHAR function.
where TO_CHAR(entity.lt_date,'YYYY-MM-DD') >= '2001-01-01'
But you don't want to do that because that's going to force Oracle to evaluate that expression on the left side for every flipping row in the table, so it has a string value to do the comparison. (That's true unless someone created a function-based index for you.) If you do the comparison on the bare column, using the TO_DATE on the literal side, Oracle can make effective use of an appropriate index (with lt_date as the leading column) to satisfy the predicate.