This question already has an answer here:
Oracle "Invalid Number" caused by to_char function
(1 answer)
Closed 6 years ago.
I have created a sql query in which I'm passing a parameter to the section shared below
BETWEEN
NVL(TO_CHAR(:DATE1, 'DD-MON-YYYY'), DATETIME)
AND
NVL(TO_CHAR(:DATE2, 'DD-MON-YYYY'), DATETIME)
When I run this query with the data type it works fine but when I run this query with VARCHAR2 parameter it gives the following error:
[Error] Execution (9: 25): ORA-01722: invalid number
When I run this query with null, the query shows up all the records.
actually I need to run this query using a STRING parameter not with the DATE dataype so when I pass the parameter to the same query in toad it will work fine even with the null values.
Here is my complete query:
SELECT rownum,ACCOUNT_NO,CUSTOMER_NAME,CARD_NO, SOURCE, ATM_ID, ISSUER_BANK_NAME,ASE.STATUS_DESC, CARD_TYPE, CARD_RESP,
DATETIME,BR_INPUT_DATE BR_ACTIVITY
FROM ATM_RCCM, ATM_STATUS_ERRORS ASE
where ASE.STATUS_DESC = NVL(:PT, ASE.STATUS_DESC)
AND BR_TRACKING_STATUS = ASE.STATUS_CODE
AND CARD_TYPE = NVL(:CT, CARD_TYPE)
AND DATETIME
BETWEEN
NVL(TO_CHAR(:DATE1, 'DD-MON-YYYY'), DATETIME)
AND
NVL(TO_CHAR(:DATE2, 'DD-MON-YYYY'), DATETIME)
Also note that the DATETIME column has the default datatype of VARCHAR2.
Elementary dear Watson: TO_CHAR converts dates to varchar2. Why do you expect it to work if you give it the wrong data type? When you give it a varchar2 input, it will (stupidly in my opinion) try to convert it to a date first, instead of throwing a compilation error. It will use your session's NLS_DATE_FORMAT though, NOT the format model you have in TO_CHAR. So in your case, it can't and it throws a runtime error.
The comparison is wrong anyway; it is pretty clear you want to compare dates, not strings. So why are you converting the dates to strings first, and then compare? With string comparisons, 12-JAN-2012 is before 9-MAR-1993.
Did you just mean to use TO_DATE, not TO_CHAR? Give it a try and see what happens! Just make sure you wrap DATETIME within TO_DATE too, with the appropriate format model.
It has to be an issue with the parameters you are entering. Likely your :DATE1 or :DATE2 are in the incorrect format, or you may have an alpha character in CT or PT
Related
I have a table with date type column.
I am trying to insert date in it:
But I get an error:
Please give me to make the correct query to put the date
Easy fix::
INSERT INTO t(dob) VALUES(DATE '2015-12-17');
Assuming this is an Oracle question based on the ORA-01843 error message, the problem appears to be in the date formatting as the error suggests.
In the provided example does the date '6-3-2012' mean '3 March 2012' or 'June 6, 2012?' The answer lies within the NLS_DATE_FORMAT parameter.
Out of the box, the Oracle date format is DD-MON-RR. So your corrected date format is either '03-MAR-12' or '06-JUN-12.' If the NLS_DATE_FORMAT has not been changed.
Never try to insert a string into a date column! If you have a string, use the to_date function with an explicit date format (and use 4 digit dates).
Relying on nls_date_format to implicitly convert your strings is just asking for trouble (like you just did), it can very easily change, even some apps will change it themselves.
The date literal (date '2015-12-17' https://docs.oracle.com/cd/B19306_01/server.102/b14200/sql_elements003.htm#BABGIGCJ) always uses the same date format so that might be okay for ad hoc statements but you need to be aware that it is literal by name and literal by nature. They don't support bind variables so you will end up writing unshareable SQL to chew up your shared pool.
I have an oracle table which has date in dd-mm-yyyy and dd/mm/yyyy format in same field. Now i have to convert into one common format.
Please suggest how to approach this?
I did tried but it is failing as it is failing due to invalid month.
Is there a way i can first identify what format the date is and then based on case statement i might convert.
or something easy way? Please
I trust you've learnt your lesson and you're now going to store these dates in the date data type.
Your two different date formats actually aren't important, Oracle already is a little over accepting when it comes to separating characters.
e.g
to_date('01/01/1900','dd-mm-yyyy')
Does not error
I did tried but it is failing as it is failing due to invalid month.
Your error is coming because you've allowed a value that doesn't match either of those formats into your string column.
If you are on version 12.2 at least (which you should be in 2020) then you can use the validate_conversion function to identify rows that don't convert to a date with your format (https://docs.oracle.com/en/database/oracle/oracle-database/12.2/sqlrf/VALIDATE_CONVERSION.html#GUID-DC485EEB-CB6D-42EF-97AA-4487884CB2CD)
select string_column
from my_table
where validate_conversion(string_column AS DATE,'dd/mm/yyyy') = 0
The other additional helper we got in 12.2 was the on conversion error clause of to_date. So you can do.
alter table my_table add my_date date;
update my_table set my_date = to_date(my_string default null on conversion error,'dd/mm/yyyy');
If you are confident that there is no other format than those two, a simple approach is replace():
update mytable set mystring = replace(mystring, '/', '-');
This turns all dates to format dd-mm-yyyy.
I would suggest taking a step forward and convert these strings to a date column.
alter table mytable add mydate date;
update mytable set mydate = to_date(replace(mystring, '/', '-'), 'dd-mm-yyyy');
This will fail if invalid date strings are met. I tend to consider that a good thing, since it clearly signals that this a problem with the data. If you want to avoid that, you can use on conversion error, available starting Oracle 12:
to_date(
replace(mystring, '/', '-') default null on conversion error,
'dd-mm-yyyy'
)
Then you can remove the string column, which is no longer needed.
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.
I have 2 parameters in my report Query of datatype date, I have selected the fnd_standard_date as value set, here is my query
Select ordered_date, order_number, customer_id
From order_tbl xx
Where NVL(:P_ORDER_NUMBER, xx.order_number) = xx.order_number
and xx.ordered_date between NVL(trunc(TO_DATE(:P_FROM_DATE, 'YYYY/MM/DD HH24:MI:SS')), xx.ORDERED_DATE) and NVL(trunc(TO_DATE(:P_TO_DATE, 'YYYY/MM/DD HH24:MI:SS'), xx.ORDERED_DATE)
AND NVL(:P_CUSTOMER, xx.customer_id) = xx.customer_id>
In SQLDeveloper the result is ok, but in Oracle apps, I am facing
java.sql.SQLDataException: ORA-01843: not a valid month
What value set can I use for this parameter?
And what format can I pass?
If your parameters are already DATEs as you say, then you should not be calling TO_DATE() for them. That will do an implicit conversion of the date to a string using the session's NLS_DATE_FORMAT, and then try to convert that string back into a date using the format model you have specified.
That will work if NLS_DATE_FORMAT happens to match what you specified, but you should not rely on that being the case, and should not do implicit conversions; and you're doing more work than you need to anyway.
So just simplify it to:
Select ordered_date, order_number, customer_id
From order_tbl xx
Where NVL(:P_ORDER_NUMBER, xx.order_number) = xx.order_number
and xx.ordered_date between NVL(trunc(:P_FROM_DATE), xx.ORDERED_DATE)
and NVL(trunc(:P_TO_DATE), xx.ORDERED_DATE)
AND NVL(:P_CUSTOMER, xx.customer_id) = xx.customer_id>
If you're running it from SQL Developer with P_DATE_FROM and _TO declared as strings via the variable command, then you will need to use TO_DATE() of course. The two situations are not the same.
Thank you very much!
The problem is with xml publisher / ebs concurrent parameters, just did the following and solved.
used the canonical_to_date in query
Where trunc(xx.ordered_date) between NVL(trunc(fnd_date.canonical_to_date(:P_FROM_DATE)), xx.ORDERED_DATE) and NVL(trunc(fnd_date.canonical_to_date(:P_TO_DATE)), xx.ORDERED_DATE)
used the FND_STANDARD_DATE value set
I have a column in a table where timestamps have been stored in VARCHAR format, but I need to compare these against a column of DATETIME values from another table to find time intervals, so I want to either cast or convert the VARCHAR timestamps to DATETIME. However, both casting and converting are giving me problems.
The format of the VARCHAR timestamp looks like this: "29/07/2012 01:53:36 +12".
Using the query:
SELECT CAST(event_timestamp AS datetime) FROM the_table
produces ERROR: date/time field value out of range: "29/07/2012 01:53:36 +12".
Using the query:
SELECT CONVERT(datetime, event_timestamp, 131) from the_table;
produces
ERROR: syntax error at or near ","
LINE 1: select CONVERT(datetime, event_timestamp, 131) from the_tab...
^ (note: this is pointing at the first comma).
The error with CONVERT actually happens even if you use a generic function such as getdate() for the data source. This db uses ANSI SQL-92 (or so I'm told). Could anyone please help me out with this?
This seems really painful, but the following should work:
select dateadd(hh, cast(right(tv, 3) as int),
CONVERT(datetime, left(tv, 10), 103)+CONVERT(datetime, substring(tv, 12, 8), 108)
)
from (select '29/07/2012 01:53:36 +12' as tv) t
I've never added datetime's before, but this just worked on SQL Server 2008.
Why can't SQL Server just support a flexible notation built around yyyy, mm, mmm, dd and so on?
The actual database is Aster Data, which is based on Postgres (as are most recent database engines). In this database, you would use to_timestamp(). See the documentation here http://www.postgresql.org/docs/8.2/static/functions-formatting.html. The call would be something like:
to_timestamp(val, 'MM/DD/YYYY HH:MI:SS tz') -- not sure if this gets the +12
There are no ANSI functions for date conversion, so each database does its own. Even string functions vary among databases (substr? substring? charindex? instr? location?), so there is no ANSI way to do this.
You are using the wrong syntax, try:
CONVERT(varchar(X), datetimeValue, 131)
Where X is the total number of characters desired.
You will then be able to search for a match with datetimeValue and event_timestamp, assuming each value share the same structure. This will allow you to match string against string.
If I'm not mistaken the standard (ANSI SQL) CAST operator always expect time/date/timstamp literals in ISO format ('YYYY-MM-DD')
But according to the manual for Teradata V12 (can't test it), the format of the CAST operator is
CAST(character_expression AS TIMESTAMP timestamp_data_attribute)
with date_data_attribute being a character value plus an optional FORMAT specifier.
So in your case this would probably be:
cast(event_timestamp AS TIMESTAMP FORMAT 'MM/DD/YYYY HH:MI:SS Z');
I'm not entirely sure about the format definition though. You'll probably need to adjust that
Btw: CONVERT isn't a standard SQL function. It's SQL Server specific.