不包含where子句的输出
表中很可能有无效的月份名。另一个证明你不应该将日期/时间值存储为字符串。始终使用正确的DATE
/TIMESTAMP
数据类型。
如果您使用Oracle 18或更新的版本,那么您可能会发现如下的无效值:
SELECT *
FROM VIEW_USER_CON_PFLANZE_ERNTE
WHERE
TO_DATE(beginn DEFAULT NULL ON CONVERSION ERROR, 'MONTH', 'NLS_DATE_LANGUAGE=German') IS NULL
OR
TO_DATE(ende DEFAULT NULL ON CONVERSION ERROR, 'MONTH', 'NLS_DATE_LANGUAGE=German') IS NULL
或者这个
WITH t AS (
SELECT beginn, ende,
VALIDATE_CONVERSION(beginn AS DATE, 'MONTH', 'NLS_DATE_LANGUAGE=German') as begin_valid,
VALIDATE_CONVERSION(ende AS DATE, 'MONTH', 'NLS_DATE_LANGUAGE=German') as end_valid
FROM VIEW_USER_CON_PFLANZE_ERNTE)
SELECT *
FROM t
WHERE begin_valid= 0 or end_valid = 0
好的,我的解决方案很简单…我在底层表的字段值中发现了一些异常然后把它们移走……它工作…
学习
- 只是因为视图工作,底层表不工作,所以你不能使用where between子句,即使你的视图工作
- 如果它不工作,在您的字段中搜索异常
- 和不要使用varchar2进行日期比较,除非绝对必要
将date
字段存储为varchar2
确实是一种不好的做法。我已经看过很多次了,它总是一个问题和问题的来源。
看看你的数据样本,在我看来,你得到错误的原因是因为你的数据中确实有无效的月份。我甚至没有考虑到"之间"您正在应用缺乏基本逻辑,因为between应该分别包括两者。原因是从to_date
的转换,从一个月给你的第一天在午夜。也许您还应该考虑使用last_day
,以便包含between条件中使用的第二个月的数据。
SQL> create table t1 ( c1 varchar2(30) , c2 varchar2(30) ) ;
Table created.
SQL> insert into t1 values ( 'JANUAR' , 'MAI' ) ;
1 row created.
SQL> insert into t1 values ( 'JANUAR' , 'FEBRUAR' );
1 row created.
SQL> select * from t1 ;
C1 C2
------------------------------ ------------------------------
JANUAR MAI
JANUAR FEBRUAR
那么,现在我们有两个varchar2
数据类型的字段,但是它们用德语包含月份。使用滤镜效果很好
SQL> select to_date(c1,'MONTH', 'NLS_DATE_LANGUAGE=German' ) as c1 ,
2 to_date(c2, 'MONTH', 'NLS_DATE_LANGUAGE=German' ) as c2,
3 sysdate-180 as date_calculation
4 from t1
5 where sysdate-180 between to_date(c1,'MONTH', 'NLS_DATE_LANGUAGE=German' )
6* and to_date(c2, 'MONTH', 'NLS_DATE_LANGUAGE=German' )
SQL> /
C1 C2 DATE_CALC
--------- --------- ---------
01-JAN-21 01-MAY-21 25-MAR-21
唯一可能的解释是你确实有一个不是有效月份的数据。您可以使用@Wernfried Domscheit提供的答案来查找哪些行不包含有效月份。
,db<的在小提琴