Я дал ниже код в запросе.
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
Может кто-нибудь сказать, почему я получаю эту ошибку?
Никогда, никогда не используйте TO_DATE()
для того, что уже является DATE
. Причина этого заключается в том, что Oracle будет вынуждена сделать некоторые неявные преобразования, чтобы следовать вашим пожеланиям:
TO_DATE(sysdate, 'mm-yyyy')
действительно выполняется как
TO_DATE(TO_CHAR(sysdate, '<default nls_date_format parameter>'), 'mm-yyyy')
поэтому, если ваш nls_date_format настроен на нечто, отличное от «mm-yyyy», у вас будут проблемы. Параметр nls_date_format по умолчанию – «DD-MON-YY», что более чем вероятно для значения, на которое установлено значение.
Если все, что вы хотели сделать, это добавить_месяца к 1-му из текущего месяца, то вы должны использовать TRUNC()
, например:
add_months(trunc(sysdate, 'MM'),-12)
Вот доказательство неявного to_char, если вы to_date то, что уже является датой, по просьбе Lalit – план выполнения базового запроса с участием 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()
в состоянии фильтра.
Ошибка здесь:
to_date (sysdate, «ММ-ГГГГ»)
Давайте посмотрим, почему:
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 на предмет понимания неявного преобразования, которое Oracle вынужден делать при применении to_date в 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