假设这DATE_ENTERED
是一VARCHAR2
列
- 您永远不应该将日期存储为字符串。日期应存储在
DATE
列中。使用错误的数据类型是问题的根源,修复数据模型以使用正确的数据类型是正确的解决方案。
- 如果要将字符串转换为日期,请
TO_DATE
使用具有显式格式掩码的函数。没有格式掩码的ACAST
或 aTO_DATE
将导致会话NLS_DATE_FORMAT
指定为格式掩码的任何内容。由于每个会话可能不同,这意味着您的代码可能适用于某些客户端的某些用户,而不适用于其他用户或其他客户端,并且不可避免地难以找到错误。
- 应始终将A
DATE
与另一个进行比较,而DATE
不是与字符串进行比较。将日期与字符串进行比较会迫使 Oracle 进行隐式转换,该转换再次使用会话NLS_DATE_FORMAT
,并再次使您的代码不可靠。如果要指定文字日期,请使用该TO_DATE
函数将字符串转换为日期(带有显式格式掩码)或使用 ANSI 日期文字
- 假设这
ID
是主键,那么DISTINCT
充其量是没有意义的,最坏的情况是迫使 Oracle 进行不必要的排序。
第一个最佳解决方案是修改数据模型DATE_ENTERED
,实际上是一个DATE
. 如果您这样做,您的查询将变为(使用 ANSI 日期文字)
SELECT id
FROM accused
WHERE date_entered BETWEEN date '2013-04-12' and date '2013-04-12'
或显式TO_DATE
SELECT id
FROM accused
WHERE date_entered BETWEEN to_date( '12-Apr-2013', 'DD-Mon-YYYY' )
AND to_date( '12-Apr-2013', 'DD-Mon-YYYY' )
如果由于某种原因,您遇到了不正确的数据模型,如果您存储的所有字符串实际上都是有效的,您可以执行类似的操作
SELECT id
FROM accused
WHERE to_date( date_entered, 'DD-Mon-YYYY' ) BETWEEN to_date( '12-Apr-2013', 'DD-Mon-YYYY' )
AND to_date( '12-Apr-2013', 'DD-Mon-YYYY' )
但是,鉴于您遇到的错误,似乎很有可能在表中至少有一些行,其中存储在表中的字符串不代表有效日期。然后问题就变成了试图找出哪些行是无效的。一种选择是创建一个新功能
CREATE OR REPLACE FUNCTION my_to_date( p_date_str IN VARCHAR2,
p_format_mask IN VARCHAR2 )
RETURN DATE
IS
l_date DATE;
BEGIN
l_date := to_date( p_date_str, p_format_mask );
RETURN l_date;
EXCEPTION
WHEN others THEN
RETURN NULL;
END;
然后在您的查询中使用该函数。
SELECT *
FROM accused
WHERE date_entered IS NOT NULL
AND my_to_date( date_entered, 'DD-Mon-YYYY' ) IS NULL
DATE_ENTERED
将返回格式中不代表有效日期的所有行DD-Mon-YYYY
。您最终必须更正这些数据。如果您可以忽略任何包含无效数据的行,则可以编写查询
SELECT id
FROM accused
WHERE my_to_date( date_entered, 'DD-Mon-YYYY' ) BETWEEN to_date( '12-Apr-2013', 'DD-Mon-YYYY' )
AND to_date( '12-Apr-2013', 'DD-Mon-YYYY' )