oracle中带日期的筛选条件无效

q35jwt9p  于 2023-05-16  发布在  Oracle
关注(0)|答案(2)|浏览(166)

我有一个查询,我想用日期参数过滤,所以我写了下面的查询。
select * from changerequests where createdon = '12-04-14'and lastmodifiedon='17-05-14';
查询执行时获取0行,而表有这么多记录。
列上的createdon和lastmodifiedon的数据类型是DATE

b1zrtrql

b1zrtrql1#

在Oracle中,DATE数据类型是一种二进制数据类型,由7个字节组成,表示世纪、世纪年、月、日、小时、分钟和秒。它总是具有这7个组件,并且从不以任何特定的人类可读格式存储。
在表中,日期存储为12-04-14
不,如果你的列是DATE数据类型,那么它不会使用这种格式存储它们。
您用来访问数据库的客户端应用程序可能使用DD-MM-RR显示日期,但它将被存储为二进制数据,没有任何人类可读的格式。
如果您这样做:

SELECT TO_CHAR(createdon, 'YYYY-MM-DD HH24:MI:SS'),
       TO_CHAR(lastmodifiedon, 'YYYY-MM-DD HH24:MI:SS')
FROM   changerequests;

然后,您应该看到日期的完整组成部分,包括时间组成部分。
当您这样做时:

SELECT *
FROM   changerequests
WHERE  createdon = '12-04-14'
AND    lastmodifiedon = '17-05-14';

那么'12-04-14'NOT一个DATE数据类型;它是一个字符串文字。
Oracle将尝试提供帮助并将其转换为日期,您的查询有效地:

SELECT *
FROM   changerequests
WHERE  createdon = TO_DATE(
         '12-04-14',
         (SELECT value FROM NLS_SESSION_PARAMETERS WHERE parameter = 'NLS_DATE_FORMAT')
       )
AND    lastmodifiedon = TO_DATE(
         '17-05-14',
         (SELECT value FROM NLS_SESSION_PARAMETERS WHERE parameter = 'NLS_DATE_FORMAT')
       );

这是不匹配的,因为日期将被赋予午夜的时间组件,而表中的日期可能具有非午夜的时间组件。
相反,您需要做的是在整个24小时内匹配时间范围:

SELECT *
FROM   changerequests
WHERE  createdon >= DATE '2014-04-12'
AND    createdon <  DATE '2014-04-13'
AND    lastmodifiedon >= DATE '2014-05-17'
AND    lastmodifiedon <  DATE '2014-05-18';

或者,使用TRUNC将时间分量截断为午夜,然后比较:

SELECT *
FROM   changerequests
WHERE  TRUNC(createdon) = DATE '2014-04-12'
AND    TRUNC(lastmodifiedon) = DATE '2014-05-17';

(* 注意:使用TRUNC将阻止Oracle在这些列上使用索引,而您需要基于函数的索引;使用日期范围将允许Oracle在这些列上使用索引,这通常是首选解决方案。*)

xyhw6mcr

xyhw6mcr2#

'12-04-14'是什么意思2012年4月14日1912年4月14日2014年4月12日...
DBMS似乎做出了猜测,但猜测与您所期望的不同。
比较日期时,使用日期文字,而不是字符串。例如:

select * 
from changerequests
where createdon = date '2014-04-12'
and lastmodifiedon = date '2014-05-17';

如果这不起作用,那么您的列可能用词不当,建议使用日期(“创建于”),而实际上是日期时间(“创建于”)。在Oracle中,这样的事情比其他DBMS中发生得更频繁,因为Oracle不恰当地将其datetime数据类型称为DATEDATE由日期部分和时间部分组成,当只处理日期时,我们将时间部分设置为午夜。
因此,如果您在列中存储时间(例如:2014-04-12 at 12:34:56),那么你就必须改变比较,因为2014-04-12 12:34:56不等于2014-04-12(分别是2014-04-12 00:00:00)。

select * 
from changerequests
where createdon >= date '2014-04-12' and createdon < date '2014-04-13'
and lastmodifiedon >= date '2014-05-17' and lastmodifiedon < date '2014-05-18';

或者,您可以将日期时间截断为午夜(即仅仅是日期)。这可能会导致查询速度变慢,因为列不能直接访问(如果您有日期索引,则该索引无法使用)。

select * 
from changerequests
where trunc(createdon) = date '2014-04-12'
and trunc(lastmodifiedon) = date '2014-05-17';

相关问题