问题
I have given the below code in query.
where to_date(cal_wid,'yyyymmdd')
between add_months(to_date(sysdate, 'MM-YYYY'),-12)
and to_date(sysdate, 'MM-YYYY')
I am getting the following bug. (I am doing in a Xampp server)
Warning: oci_execute(): ORA-01843: not a valid month in C:\xampp\htdocs\xxx\index.php on line 149
Warning: oci_fetch_array(): ORA-24374: define not done before fetch or execute and fetch in C:\xampp\htdocs\xxx\index.php on line 160
Can anyone tell why I am getting this error?
回答1:
Never, ever use TO_DATE()
on something that is already a DATE
. The reason for this is because Oracle will have to do some implicit conversions in order to follow your wishes:
TO_DATE(sysdate, 'mm-yyyy')
is really run as
TO_DATE(TO_CHAR(sysdate, '<default nls_date_format parameter>'), 'mm-yyyy')
so if your nls_date_format is set to something that's other than 'mm-yyyy', you're going to have problems. The default nls_date_format parameter is 'DD-MON-YY', which is more than likely the value yours is set to.
If all you wanted to do was to add_months to the 1st of the current month, then you should use TRUNC()
, eg:
add_months(trunc(sysdate, 'MM'),-12)
Here's proof of the implicit to_char if you to_date something that's already a date, as requested by Lalit - an execution plan of a basic query involving to_date(sysdate):
SQL_ID 3vs3gzyx2gtcn, child number 0
-------------------------------------
select * from dual where to_date(sysdate) < sysdate
Plan hash value: 3752461848
----------------------------------------------------------------------------
| Id | Operation | Name | E-Rows |E-Bytes| Cost (%CPU)| E-Time |
----------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 2 (100)| |
|* 1 | FILTER | | | | | |
| 2 | TABLE ACCESS FULL| DUAL | 1 | 2 | 2 (0)| 00:00:01 |
----------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter(TO_DATE(TO_CHAR(SYSDATE@!))<SYSDATE@!)
You can clearly see the TO_CHAR()
in the filter condition.
来源:https://stackoverflow.com/questions/29141671/not-a-valid-month-in-oracle-when-add-months-is-used