ORA-01839 “date not valid for month specified” for to_date in where clause

匿名 (未验证) 提交于 2019-12-03 00:57:01

问题:

I have following query (BOCRTNTIME - varchar e.g 2015-02-28 12:21:45, VIEW_BASE_MARIX_T - some view):

select BOCRTNTIME     from VIEW_BASE_MARIX_T     where to_date(substr(BOCRTNTIME,1,10),'YYYY-MM-DD')         between (to_date ('2016-01-01', 'YYYY-MM-DD'))             and (to_date ('2016-02-01', 'YYYY-MM-DD')) 

On executing I get error:

ORA-01839:  "date not valid for month specified" 

I thought that there are can be incorrect data in BOCRTNTIME, so execute following query:

select distinct          substr(BOCRTNTIME,1,8),          substr(BOCRTNTIME,9,2)   from VIEW_BASE_MARIX_T  order by substr(BOCRTNTIME,9,2); 

But everything looks fine: http://pastebin.com/fNjP4UAu. Also following query executes without any error:

select to_date(substr(BOCRTNTIME,1,10),'YYYY-MM-DD')    from VIEW_BASE_MARIX_T; 

I already tried add trunc() to all to_date() but no luck. Also I create pl/sql procedure that takes one by one item form VIEW_BASE_MARIX_T and convert it to date - and everything works just fine. Any ideas why I get error on first query?

UPD: Query on table that used in view works fine, but in view - not

UPD2: We have few enviroments with same products, but get error only on one

UPD3: Issue was resolved by search non valid dates in table that used in view

回答1:

I think that what might be happening is that Oracle is pushing the predicate to the underlying tables of the view.

Have you tried to run the query

select to_date(substr(BOCRTNTIME,1,10),'YYYY-MM-DD') BOCRTNTIME from MY_TABLE 

instead of querying the view?

you can also confirm this by using the NO_PUSH_PRED hint

select /*+ NO_PUSH_PRED(VIEW_BASE_MARIX_T) */ BOCRTNTIME from VIEW_BASE_MARIX_T where  to_date(substr(BOCRTNTIME,1,10),'YYYY-MM-DD') between (to_date ('2016-01-01', 'YYYY-MM-DD')) and (to_date ('2016-02-01', 'YYYY-MM-DD')) 


回答2:

A bit too long for a comment - create a simple function to test the dates:

CREATE FUNCTION is_Valid_Date(   in_string VARCHAR2,   in_format VARCHAR2 DEFAULT 'YYYY-MM-DD' ) RETURN NUMBER DETERMINISTIC AS   dt DATE; BEGIN   dt := TO_DATE( in_string, in_format );   RETURN 1; EXCEPTION   WHEN OTHERS THEN     RETURN 0; END; / 

Then you can do:

SELECT BOCRTNTIME FROM   VIEW_BASE_MARIX_T WHERE  is_Valid_Date( substr(BOCRTNTIME,1,10) ) = 0; 

You will possibly find that April, June, September or November have an entry for the 31st of that month or February has values greater than 28/29th (although I can't see anything like that in your pasted data).

Otherwise you could try using ANSI Date literals:

SELECT BOCRTNTIME FROM   VIEW_BASE_MARIX_T WHERE  to_date(substr(BOCRTNTIME,1,10),'YYYY-MM-DD') between DATE '2016-01-01' and DATE '2016-02-01'; 

or, even simpler, given the format of the input:

SELECT BOCRTNTIME FROM   VIEW_BASE_MARIX_T WHERE  substr(BOCRTNTIME,1,10) between '2016-01-01' and '2016-02-01'; 


回答3:

The error message says that you have an invalid day in your month. Check your data with this:

-- Check for months with 30 days select substr(BOCRTNTIME,9,2), substr(BOCRTNTIME,6,2) from VIEW_BASE_MARIX_T where to_number(substr(BOCRTNTIME,6,2)) in (4,6,9,11) and to_number(substr(BOCRTNTIME,9,2))>30;  -- Check for february select substr(BOCRTNTIME,9,2), substr(BOCRTNTIME,6,2) from VIEW_BASE_MARIX_T where to_number(substr(BOCRTNTIME,6,2))=2 and to_number(substr(BOCRTNTIME,9,2))>28; 


回答4:

It might be a long shot but between doesn't have parenthesis in it's syntax, have you tried removing them?

select     BOCRTNTIME     from VIEW_BASE_MARIX_T     where      to_date(substr(BOCRTNTIME,1,10),'YYYY-MM-DD') between to_date ('2016-01-01', 'YYYY-MM-DD') and to_date ('2016-02-01', 'YYYY-MM-DD') 


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!