【问题标题】:oracle between month name月份名称之间的oracle
【发布时间】:2021-11-15 04:01:30
【问题描述】:

我的输出没有 where 子句(示例)

ID NAMEN NAME BEGINN ENDE
108129 Kürbis, Gartenkürbis, Feldkürbis Blüten Juli Juli
126611 Nussbaum, Walnuss, Christnuss Schalen August September
126611 Nussbaum, Walnuss, Christnuss Früchte Oktober Oktober
126611 Nussbaum, Walnuss, Christnuss Blätter Juni Juni
92542 Beifuß Stabkraut, Besenkraut Blätter Juni Juni
92542 Beifuß Stabkraut, Besenkraut Wurzeln September November

您好,我尝试在 beginn(例如 Juli)和 ende(例如 Dezember)(varchar2) 之间选择条目。

select * from (
    select * from VIEW_USER_CON_PFLANZE_ERNTE
    )
where sysdate 
between to_date(beginn, 'MONTH', 'NLS_DATE_LANGUAGE=German')
and to_date(ende, 'MONTH', 'NLS_DATE_LANGUAGE=German')

但我收到错误:ORA-01843: not a valid month

最后,我想实现这一点:


where sysdate
...
and last_day(to_date(ende, 'DD.MONTH', 'NLS_DATE_LANGUAGE=German'))

从双重作品中选择to_date(beginn, 'MONTH', 'NLS_DATE_LANGUAGE=German')* and *to_date(ende, 'MONTH', 'NLS_DATE_LANGUAGE=German'),我得到两者的 MM/DD/YYYY

【问题讨论】:

  • beginnende 已经是日期数据类型了吗?如果是,您可以使用 EXTRACT 函数而不是 TO_DATE。
  • 抱歉,没有它的 varchar2
  • 请提供一些存储在这些字段中的示例数据。
  • edit your question将该数据添加为格式化文本。视图查询是否也在自己将字符串转换为日期 - 使用会话数据语言?
  • 不管您的直接问题是什么,您是否意识到像您一样在月份名称上使用to_date包括七月,例如,如果@ 987654329@ 是'Juli'to_date 您调用它的方式将返回当年的 7 月 1 日,时间 00:00:00 - 这意味着“在……和……之间”将是“在……和 7 月 1 日午夜之间” - 在 7 月省略任何内容(7 月 1 日午夜除外)。

标签: sql oracle date where-clause between


【解决方案1】:

您的表中很可能存在无效的月份名称。另一个证明您应该从不将日期/时间值存储为字符串。始终使用正确的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

【讨论】:

  • 是的,你是绝对正确的。将日期存储为 varchar2 不是一个好主意,但现在,我别无选择。您的两个脚本都导致找不到数据
  • 编辑: 如果我在脚本中使用基础表,我会得到结果。 beginn 和 ende 的验证为 0。在视图中我只看到 1(如果我忽略你的 whereclause)
【解决方案2】:

好的,我的解决方案很简单...我在基础表的字段值中发现了一些异常并将它们删除...它有效...

学习

  • 仅仅因为视图有效,基础表不起作用,所以即使视图有效,也不能使用 where 子句
  • 如果不起作用,请在您的字段中搜索异常
  • 除非绝对必要,否则不要使用 varchar2 进行日期比较

【讨论】:

    【解决方案3】:

    date 字段存储为varchar2 确实是一种不好的做法。我已经看过很多次了,它始终是问题和问题的根源。

    查看您的数据样本,在我看来,您收到错误的原因是因为您的数据中确实存在无效月份。我什至不认为您应用的“之间”缺乏基本逻辑,因为之间应该分别包括两者。原因是从to_date 转换为从给您第一天午夜的月份的转换。也许您也应该考虑使用last_day,以便在中间条件中包含第二个月的数据。

    演示

    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<>fiddle

    【讨论】:

    • 样本数据现在可用 :) 抱歉,我真的认为在那种情况下,这没有任何意义
    • 使用您的数据样本,它可以正常工作。因此,您的数据中没有有效月份。这是唯一的解释。
    • 我的基础表有一些问题,在视图中不可见。我解决了这些问题,它可以工作... g2k:只是因为视图有效,基础表不起作用,所以即使您的视图有效,您也不能使用 where between 子句
    • 你永远不会在视图中看到它。视图是一种逻辑结构,是嵌入在对象中的选择,在执行之前与数据无关。只要 sql 有效,您的视图就会编译,但在您对其进行选择之前,它不会检查数据。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-02-29
    • 2011-05-28
    • 2017-02-19
    • 2020-12-07
    • 1970-01-01
    相关资源
    最近更新 更多