1

What is wrong with this sql?

This gives me 0 results:

Select * from DOC where CREATION_TIME > to_TIMESTAMP('01-Jan-69 11.59.16 AM','dd-Mon-YY HH12.mi.ss.FF3AM');

When I run this as:

Select * from DOC where CREATION_TIME > '01-JAN-69 11.59.16.000000000 AM';

I get results just fine. The table schema is setup with CREATION_TIME as a Timestamp type with the format seen in the second query.

1
  • You are wise to want to use to_timestamp() and not rely on implicit conversions (which are correct 50% of the time at best). Do not let this incident (the "Y2K problem") discourage you from the best practice, which is to use to_timestamp() as you were trying to. That's the right way to write queries. Commented Dec 7, 2016 at 23:57

2 Answers 2

1

This is because,

select TO_TIMESTAMP('01-Jan-69 11.59.16 AM','dd-Mon-YY HH12.mi.ss.FF3AM') from dual

returns 01.01.2069 11:59:16 (note 2069 instead of 1969 here)

To convert to the correct year use,

TO_TIMESTAMP('01-Jan-69 11.59.16 AM','dd-Mon-RR HH12.mi.ss.FF3AM')

From the documentation

The RR datetime format element is similar to the YY datetime format element, but it provides additional flexibility for storing date values in other centuries. The RR datetime format element lets you store 20th century dates in the 21st century by specifying only the last two digits of the year.

If you use the TO_DATE function with the YY datetime format element, then the year returned always has the same first 2 digits as the current year. If you use the RR datetime format element instead, then the century of the return value varies according to the specified two-digit year and the last two digits of the current year.

If the specified two-digit year is 00 to 49, then

  • If the last two digits of the current year are 00 to 49, then the returned year has the same first two digits as the current year.

  • If the last two digits of the current year are 50 to 99, then the first 2 digits of the returned year are 1 greater than the first 2 digits of the current year.

If the specified two-digit year is 50 to 99, then

  • If the last two digits of the current year are 00 to 49, then the first 2 digits of the returned year are 1 less than the first 2 digits of the current year.

  • If the last two digits of the current year are 50 to 99, then the returned year has the same first two digits as the current year.

Sign up to request clarification or add additional context in comments.

2 Comments

And when using month names one should specify the NLS_DATE_LANGUAGE in TO_TIMESTAMP's third parameter.
@vkp thank you very much that was very informative and easy fix. Drove me nuts for a lot longer than it should have.
1

You probably feel very lucky assuming a string will be translated correctly as a timestamp.

The ANSI/ISO way to notate a timestamp literal is timestamp yyyy-mm-dd[.ff] hh24:mi:ss, e.g. -

select timestamp '1969-01-01 11:59:16' from dual;

select timestamp '1969-01-01 11:59:16.123' from dual;

2 Comments

Both observations are correct, but they do not answer the OP's question, which was: what's wrong with the to_timestamp() call.
@mathguy, actually the question was "What is wrong with this sql?". The way the OP tried to notate the timestamps is wrong, today it caused a century issue and tomorrow it will be invalid month.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.