如何解决此选择在oracle中的错误?

时间:2019-01-14 09:13:46

标签: oracle

我想从06/01/2019到09/01/2019范围内进行选择,但是程序会返回其他范围,例如显示图像。

请记住,我在数据库中的日期字段是varchar2,我以dd / MM / yyyy的格式存储它

image

2 个答案:

答案 0 :(得分:1)

如果您希望06/08值表示天,请明确:

BETWEEN TO_DATE('06/01/2019','DD/MM/YYYY')
AND TO_DATE('09/01/2019','DD/MM/YYYY')

当前它以月为单位返回06/08值,通常在比较日期列时使用dates and not strings

  

我强烈建议您使用to_date避免歧义(将字符串与字符串,数字与数字,日期与日期进行比较-不要将字符串与数字,日期与字符串进行比较时造成混淆)。

答案 1 :(得分:1)

扩展@ user7294900的答案,因为您将“日期”值存储为字符串,所以必须将列值和目标范围值都从字符串转换为实际日期。

如果您这样做:

WHERE DATA_TRANSACAO BETWEEN '06/01/2019' AND '09/01/2019'

然后您将在列值和这些文字之间进行字符串比较,并以字符串形式 以'07'或'08'开头(大多数以'06'开头)的任何内容该范围的一部分。 Oracle纯粹将它们视为字符串,它不知道或不在乎您有几天和几个月的概念,还是您认为顺序是不同的。

如果您确实对字符串感到困惑,则需要将比较的两边都与日期进行比较:

WHERE TO_DATE(DATA_TRANSACAO, 'DD/MM/YYYY') BETWEEN TO_DATE('06/01/2019', 'DD/MM/YYYY')
  AND TO_DATE('09/01/2019', 'DD/MM/YYYY')

或使用ANSI文字:

WHERE TO_DATE(DATA_TRANSACAO, 'DD/MM/YYYY') BETWEEN DATE '2019-06-01' AND DATE '2019-01-09'

或(但是,如果可以在非午夜时间(这在数据中不是这种情况,则更有用):

WHERE TO_DATE(DATA_TRANSACAO, 'DD/MM/YYYY') >= DATE '2019-06-01'
AND TO_DATE(DATA_TRANSACAO, 'DD/MM/YYYY') < DATE '2019-01-10' -- notice one day later

您还应该意识到,必须先转换数据中的每一行的字符串值,然后才能进行比较,这意味着如果该列上有简单索引,则无法使用它,并且即使在很小的目标日期范围内,也将进行全表扫描。 (您可以添加基于函数的索引来加快此过程,但这是一个固定的方法。)

这种东西是why you should be using the correct data type。也不需要分别存储日期和时间部分,这使得其他类型的比较和数据提取比原来需要的更加困难和复杂。

我真的建议您重新访问数据模型,并从DATA_TRANSACAOHORA_TRANSACAO的单独字符串更改为一个单独的DATE列,其中包含适当的整个日期/时间值数据类型。然后,您将能够使用更简单的形式,而无需转换表数据,例如(具有组合的列名):

WHERE DATAHORA_TRANSACAO >= DATE '2019-06-01'
AND DATAHORA_TRANSACAO < DATE '2019-01-10' -- notice one day later