如果我有这样的查询:
select *
from CAT_ACCT_AUDIT_TRAIL cataccount0_
where cataccount0_.CAAT_EXECUTED_DATE >=TO_DATE(’26-AUG-2016′, ‘DD-MM-YYYY’) AND
to_Date(TO_CHAR(cataccount0_.CAAT_EXECUTED_DATE , ‘dd -mon-yyyy’), ‘DD-MM-YYYY’)<=TO_DATE('31-AUG-2016', 'DD-MM-YYYY')
为什么我们需要to_char
或to_date
函数?使用它们的正确背景是什么?
如果我做其中任何一个:
select TO_DATE('26-AUG-2016', 'DD-MM-YYYY') from dual;
select TO_DATE('01-12-2016', 'DD-MM-YYYY') from dual;
我在会话中设置的NLS变量格式输出,无论格式转换中的日期输入如何;我得到了两个相同的结果。 Wy是这样的吗?
解决此查询的正确方法是什么?我的意思是当我需要获取日期范围内的值时。
答案 0 :(得分:7)
使用to_date()
将'01-12-2016'
之类的字符串转换为date数据类型。您使用to_char()
将日期转换为字符串。在这两种情况下,您都指定了字符串的format - 如果不这样做,则会使用您的会话NLS设置,这对于除了即席查询之外的任何事情都不是好习惯,因为之后运行代码的其他人可能会有所不同输出或错误。
您的代码遵循的一般规则是将一种类型的数据与相同类型的值/常量进行比较。由于您的列是日期,因此您将过滤器值作为日期提供 - 通过将字符串转换为日期数据类型。如果你没有这样做,那么就会发生隐式转换,但是你不应该依赖它,因为它也可能导致NLS问题,并且根据它可以防止使用索引的类型。 Read more about data conversion in the documentation
Oracle在执行to_date()
时解释字符串时会尝试灵活。当您执行TO_DATE('26-AUG-2016', 'DD-MM-YYYY')
时,您将月份作为字符串提供(使用特定语言,这是另一个主题),但告诉函数期望一个数字。无论如何,甲骨文“有帮助”地解释了这一点,所以它通常有效。但无论您使用to_date()
的格式,都没有指定显示格式,因此您的客户端决定如何将转换后的日期显示为字符串 - 通常再次使用您的NLS设置。
这样做:
to_Date(TO_CHAR(cataccount0_.CAAT_EXECUTED_DATE , ‘dd -mon-yyyy’), ‘DD-MM-YYYY’)
通常毫无意义,但即使如此,也应使用一致的格式模型。有时这样做的一个原因是,如果源日期(此处caat_executed_date
)的时间设置为午夜以外的其他时间,并且您想要丢弃时间。但有更好的方法可以做到这一点 - 特别是trunc()
函数,默认情况下将时间设置为午夜。
如果您拥有常量值,例如TO_DATE('31-AUG-2016', 'DD-MM-YYYY')
,则还可以DATE '2016-08-31'
的形式使用ANSI date literals。
答案 1 :(得分:4)
目前还不清楚你想做什么,但实际上你并不需要这些常量函数。只需使用date
关键字作为日期文字即可。例如:
where cataccount0_.CAAT_EXECUTED_DATE >= date '2016-08-26'
如果要从日期中删除时间组件,请使用trunc()
:
where trunc(cataccount0_.CAAT_EXECUTED_DATE, 'dd') -- the `'dd'` is optional for this purpose
这可以在接受日期常量的任何上下文中使用。