如果我有这样的疑问:
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 变量格式的输出,无论格式转换中输入的日期如何;我对两者都得到相同的结果。为什么会这样?
解决这个问题的正确方法是什么?我的意思是当我需要获取日期范围内的值时。
to_date()
将 '01-12-2016'
等字符串转换为日期数据类型。您可以使用 to_char()
将日期转换为字符串。在这两种情况下,您都指定字符串的 format - 如果您不这样做,则使用您的会话 NLS 设置,这对于除临时查询之外的任何操作都不是一个好习惯,因为稍后运行您的代码的其他人可能会得到不同的输出或一个错误。
您的代码遵循的一般规则是将一种类型的数据与相同类型的值/常量进行比较。由于您的列是日期,因此您将通过将字符串转换为日期数据类型来将过滤器值作为日期提供。如果您不这样做,那么就会发生隐式转换,但您也不应该依赖它,因为它也可能导致 NLS 问题,并且根据类型,它可能会阻止使用索引。 阅读文档中有关数据转换的更多信息。
当您这样做时,Oracle 在解释字符串时会尝试保持灵活性
to_date()
。当您执行 TO_DATE('26-AUG-2016', 'DD-MM-YYYY')
时,您将以字符串形式提供月份(使用特定语言,这是另一个主题),但告诉函数需要一个数字。不管怎样,Oracle 都会“有帮助地”解释这一点,所以它通常是有效的。但无论您使用哪种格式 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')
,您还可以使用 ANSI 日期文字,形式为 DATE '2016-08-31'
。
目前还不清楚你想要做什么,但你实际上并不需要常量上的这些函数。 只需使用
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
这可以在任何接受日期常量的上下文中使用。