我在查询中提供了以下代码。
where to_date(cal_wid,'yyyymmdd')
between add_months(to_date(sysdate, 'MM-YYYY'),-12)
and to_date(sysdate, 'MM-YYYY')
我收到以下错误。 (我在Xampp服务器上做)
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
有人能说出我为什么会收到此错误吗?
答案 0 :(得分:5)
永远不要在已经TO_DATE()
的内容上使用DATE
。这是因为Oracle必须进行一些隐式转换才能满足您的愿望:
TO_DATE(sysdate, 'mm-yyyy')
实际上是以
运行的 TO_DATE(TO_CHAR(sysdate, '<default nls_date_format parameter>'), 'mm-yyyy')
所以,如果你的nls_date_format被设置为除了&#39; mm-yyyy&#39;以外的东西,你就会遇到问题。默认的nls_date_format参数是&#39; DD-MON-YY&#39;,这很可能是您的值设置为。
如果您只想将add_months添加到当月的第1天,那么您应该使用TRUNC()
,例如:
add_months(trunc(sysdate, 'MM'),-12)
如果你按照Lalit的要求发送一个已经是日期的东西,这是隐式to_char的证据 - 一个涉及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@!)
您可以在过滤条件中清楚地看到TO_CHAR()
。
答案 1 :(得分:1)
错误在于:
to_date(sysdate,&#39; MM-YYYY&#39;)
让我们看看原因:
SQL> select to_date(sysdate, 'MM-YYYY') from dual;
select to_date(sysdate, 'MM-YYYY') from dual
*
ERROR at line 1:
ORA-01843: not a valid month
SQL>
您不需要再次将sysdate转换为日期。删除to_date
,然后使用 SYSDATE 。
注意作为附加信息,请查看@ Boneist&#39; answer,了解有关Oracle在应用 to_date <时必须执行的隐式转换的见解/ strong> on SYSDATE
。
您使用to_date将字符串转换为日期。对于日期计算,您只需使用日期值。
例如,
SQL> WITH DATA AS(
2 SELECT '20150101' cal_wid FROM DUAL
3 )
4 SELECT *
5 FROM DATA
6 WHERE to_date(cal_wid,'yyyymmdd')
7 BETWEEN add_months(SYSDATE,-12)
8 AND SYSDATE
9 /
CAL_WID
--------
20150101
SQL>
将您的查询修改为:
WHERE to_date(cal_wid,'yyyymmdd') BETWEEN add_months(SYSDATE, -12) AND SYSDATE