我有Oracle表Demo_t
,其列end_date
的值可能为null。我想选择end_date
大于当前日期的所有行。
我在下面写了查询
select * from Demo_t where NVL(End_date,sysdate+3) > sysdate;
毫无疑问,查询给出了预期的结果,但我想确保我没有遗漏某些东西,或者存在任何其他更好的解决方案。它将帮助我更好地理解Oracle数据库。
谢谢,
答案 0 :(得分:5)
如果End_Date
为空,则将其记录在结果中。那是你要的吗?
如果是这样,你可以像
SELECT *
FROM DEMO_T
WHERE END_DATE > SYSDATE OR END_DATE IS NULL;
如果您不想要,可以尝试
SELECT *
FROM DEMO_T
WHERE END_DATE > SYSDATE;
在您的代码中:
NVL(End_date,sysdate+3)
实际上会为表格中的每一行增加sysdate
,如果您只需检查End_Date
是否为null就不是一个好主意
击>
编辑:正如@Thorsten Kettner所说,查询中只有一个sysdate,因此不会为每一行计算
答案 1 :(得分:1)
你查询没问题。您可以使用它或使用(end_date > sysdate or end_date is null)
明确地检查NULL。两者都做同样的事情,而有些人更喜欢前者,有些人更喜欢后者,有些人总是使用DECODE
来检查可空列。使用您认为最具可读性的内容并坚持在所有查询中(或在团队中:使用同事使用的内容)。保持一致。
但是,有一种方法可以加快此类查询:使用高修复日期而不是SYSDATE+3
,通常类似于DATE'9999-12-31'
。然后在此表达式上创建一个函数索引。
create index idx_end_date on demo_t ( nvl(end_date, date'9999-12-31') );
匹配查询:
select * from demo_t where nvl(end_date, date'9999-12-31') > sysdate;
由于索引涵盖所有日期,因此使用它的可能性要高于end_date
上的单纯索引。这可以极大地加速查询。
顺便提一下:请注意SYSDATE
包含时间部分。如果end_date
仅包含日期,那么您可能希望在比较中TRUNC(SYSDATE)
。
答案 2 :(得分:0)
您应该使用trunc
作为日期,否则它会比较时间并可能输出错误。
select *
from Demo_t
where trunc(nvl(end_date,sysdate+1)) > trunc(sysdate);