Skip to Main Content
  • Questions
  • Convert a String to DATE only if the format does fit exactly to the given format mask

Breadcrumb

Question and Answer

Tom Kyte

Thanks for the question, Andre.

Asked: May 03, 2007 - 9:00 am UTC

Last updated: September 24, 2007 - 7:39 am UTC

Version: 9.2.0.8

Viewed 10K+ times! This question is

You Asked

Hi Tom,

Can you explain to my these behaviour below.
I want to check if the source data has a valid DATE format fitting exactly to the given format mask.
If the given string (to be converted to DATE) has not the appropriated given format mask Oracle shout not try to be ¿clever¿ and so it never should just perform an arbitrary conversion and look what probably could fit anyway.

Is there a way to force a absolutely stringent behaviour for the converting to square with the given format mask?

Here some simple examples:

SELECT TO_DATE ('2006.02.12', 'DD-MM-YYYY HH24:MI:SS')
FROM DUAL
--> accepted result: Exception ORA-01861
--> adduced result: 20.06.0002 12:00:00
-- ??

SELECT TO_DATE ('2006.02.12', 'DD-MM-YYYY')
FROM DUAL
--> expected result: Exception ORA-01861
--> adduced result: Exception ORA-01861
--> OK

SELECT TO_DATE ('02.12-2006', 'DD-MM-YYYY HH24:MI:SS')
FROM DUAL
--> expected result: Exception ORA-01861
--> adduced result: 2.12.2006
--> ??

SELECT TO_DATE ('02.12-2006', 'DD-MM-YYYY')
FROM DUAL
--> expected result: Exception ORA-01861
--> adduced result: 2.12.2006
--> ??

Thanks and Regards
Andre

and Tom said...

use the FX format exact modifier


ops$tkyte%ORA10GR2> SELECT TO_DATE ('2006.02.12', 'fxDD-MM-YYYY HH24:MI:SS')
  2  FROM DUAL
  3  /
SELECT TO_DATE ('2006.02.12', 'fxDD-MM-YYYY HH24:MI:SS')
                *
ERROR at line 1:
ORA-01861: literal does not match format string


ops$tkyte%ORA10GR2> SELECT TO_DATE ('2006.02.12 12:34:56', 'fxDD-MM-YYYY HH24:MI:SS')
  2  FROM DUAL
  3  /
SELECT TO_DATE ('2006.02.12 12:34:56', 'fxDD-MM-YYYY HH24:MI:SS')
                *
ERROR at line 1:
ORA-01861: literal does not match format string


ops$tkyte%ORA10GR2> SELECT TO_DATE ('02-12-2006 12:34:56', 'fxDD-MM-YYYY HH24:MI:SS')
  2  FROM DUAL
  3  /

TO_DATE('02-12-20061
--------------------
02-dec-2006 12:34:56


Rating

  (3 ratings)

Is this answer out of date? If it is, please let us know via a Comment

Comments

Thank you

Andre Meier, June 01, 2007 - 2:39 am UTC

Thank you Tom!
This hint is very worthwhile.
I have to say that I never used this "fx" before.
Probably because I did not know about it ...

Andre
Tom Kyte
June 01, 2007 - 11:58 am UTC

fx and fm - very useful to_xxxx format modifiers.

Pramod, June 04, 2007 - 12:36 pm UTC

Useful info.
but I am still unable to understand why the below code works (even if giving wrong answer).


1  SELECT TO_DATE ('02.12-2006', 'DD-MM-YYYY')
  2* FROM DUAL
SQL> /
12/02/2006 00:00:00

Tom Kyte
June 06, 2007 - 9:51 am UTC

because - and / are similar to "whitespace might be here" without the format exact specification.

ak, September 20, 2007 - 11:42 am UTC

Hi TOM,

When i try to fire this query:

SELECT col.id
FROM cust_order_lines col,
order_line_params ol,
order_line_params o2
WHERE col.id = ol.order_line_id
AND ol.NAME = 'olRequiredByDateTime'
AND o2.NAME = 'olSimProvideIndicator'
AND o2.VALUE = 'Y'
AND to_date(ol.VALUE,'fxDD-MM-YYYY HH24:MI') + 1 < TO_DATE('20-09-2007 00:00','fxDD-MM-YYYY HH24:MI')
AND col.execution_status NOT IN ('COMPLETE',
'CANCELLED',
'AUTO_ABORTED',
'NORMAL',
'MANUALLY_ABORTED',
'MANUALLY_COMPLETE',
'MANUALLY_COMPLETED',
'MANUALLY_CANCELLED')

it gives the following error:

ERROR at line 9:
ORA-01840: input value not long enough for date format

Please can you suggest on this.

Thanks & Regards;
ak

Tom Kyte
September 24, 2007 - 7:39 am UTC

I'll guess that ol.value contains lots of data, data other than stuff in the format dd-mm-yyyy hh24:mi

eg: you have that "funky data model whereby we just store everything in a string"


And you think predicates are evaluated in some precise order (they are not)

likely you have to:

case when <some condidition is true> then to_date( ol.value, .... ) end


that is, check the condition that tells you "ol.value is a date hiding in a silly string" before applying to_date to it.


ops$tkyte@ORA920> create table t ( typ varchar2(1), val varchar2(30) );

Table created.

ops$tkyte@ORA920> insert into t values ( 'N', 12 );

1 row created.

ops$tkyte@ORA920> insert into t values ( 'D', '01-01-2007 00:00' );

1 row created.

ops$tkyte@ORA920>
ops$tkyte@ORA920> select * from t where typ='D' and to_date( val, 'fxDD-MM-YYYY HH24:MI' )< sysdate;
select * from t where typ='D' and to_date( val, 'fxDD-MM-YYYY HH24:MI' )< sysdate
                                           *
ERROR at line 1:
ORA-01840: input value not long enough for date format


ops$tkyte@ORA920> select * from t where to_date( val, 'fxDD-MM-YYYY HH24:MI' )< sysdate and typ='D';

T VAL
- ------------------------------
D 01-01-2007 00:00

ops$tkyte@ORA920> select * from t where typ='D' and case when typ='D' then to_date( val, 'fxDD-MM-YYYY HH24:MI' ) end < sysdate;

T VAL
- ------------------------------
D 01-01-2007 00:00

ops$tkyte@ORA920> select * from t where case when typ='D' then to_date( val, 'fxDD-MM-YYYY HH24:MI' ) end < sysdate and typ='D';

T VAL
- ------------------------------
D 01-01-2007 00:00