比较存储在date和varchar列中的日期

时间:2017-06-23 10:25:36

标签: sql oracle date datetime plsql

我有一个简单的表,我必须在DATE和VARCHAR2列中存储日期信息:

CREATE TABLE date_test(date_in_varchar VARCHAR2(30), date_in_date DATE);

INSERT INTO date_test values ('06/21/2017 01:30:00 AM', to_date('06/21/2017 01:01:03 AM', 'MM/DD/YYYY HH:MI:SS AM'));

INSERT INTO date_test values ('06/22/2017 02:45:00 AM', to_date('06/22/2017 05:06:01 AM', 'MM/DD/YYYY HH:MI:SS AM'));

INSERT INTO date_test values ('06/23/2017 05:51:20 AM', to_date('06/23/2017 12:00:05 AM', 'MM/DD/YYYY HH:MI:SS AM'));

如您所见,数据格式为' MM / DD / YYYY HH:MI:SS AM '。我必须准备在变量 l_attr_val 格式' MM / DD / YYYY' 中传递的日期与存储在表格中的日期之间的比较。现在我的问题是:为过滤器编写查询的最佳和最安全的方法是什么?等于,更大,更低,确定,我不会面对隐式转换?我假设,对于存储为日期的值和存储为varchar的值,该查询将有所不同。

案例1:日期存储在DATE列中,其中包含day, month, year, hour, minutes, seconds.的信息我还有一个变量(VARCHAR2类型),其中只有day, month, year的信息}。 (l_attr_val = '06/21/2017')。现在我想在这个变量和表中存储的值之间进行相等的过滤,只根据日期,没有时间(我在2017年6月21日变量,我希望看到2017年6月21日的所有记录,无论时间)。

SELECT * FROM date_test WHERE date_in_date = TO_DATE('06/22/2017', 'MM/DD/YYYY');

由于时间的原因,它给了我0行。

案例2,与案例1分开: 情况1:日期存储在VARCHAR2列中,其中包含day, month, year, hour, minutes, seconds.的信息。我还有一个变量(VARCHAR2类型),其信息仅为day, month, year(l_attr_val = '06/21/2017')。现在我想在这个变量和表中存储的值之间进行相等的过滤,只根据日期,没有时间(我在2017年6月21日变量,我希望看到2017年6月21日的所有记录,无论时间)。

SELECT * FROM date_test WHERE TO_DATE(date_in_varchar, 'MM/DD/YYYY HH:MI:SS AM' = TO_DATE('06/22/2017', 'MM/DD/YYYY');

那么,在上述案例中比较日期最安全的方法是什么?

3 个答案:

答案 0 :(得分:2)

案例1:正确存储的日期(日期类型)

您可以将date_in_date列转换为删除时间部分,但这不会利用此列上的非功能性索引,因此我建议不要这样做。相反,如果06/22/2017是您的VARCHAR2类型变量,您还可以动态修改它以再增加一个值,增加1天。这将在date_in_date函数上使用普通索引,查询将如下所示:

SELECT * FROM date_test
WHERE date_in_date >= TO_DATE('06/22/2017', 'MM/DD/YYYY')
  AND date_in_date < TO_DATE('06/23/2017', 'MM/DD/YYYY')

您还可以在第二部分之后添加+1,并使用相同的变量为您节省自己在变量上进行数学运算的时间。

案例2:存储为varchars的日期

您需要将date_in_varchar转换为没有时间部分的日期(或使用它,然后部分应用针对案例1的逻辑),并以相同的方式转换输入变量。如果您决定将其转换为没有时间部分的日期,那么下面的查询将利用功能索引(但不是简单的):

SELECT * FROM date_test
WHERE TO_DATE(SUBSTR(date_in_varchar, 0, 12), 'MM/DD/YYYY') = TO_DATE('06/22/2017', 'MM/DD/YYYY')

如果您决定将其转换为具有时间的日期,则部分查询将类似于案例1,但具有适当的格式。我建议你在日期转换时创建一个功能索引,将varchar修剪为只包含日期的字符,如果你的查询准确到一天。

答案 1 :(得分:2)

如果这些列上有索引,我会使用:

案例1:

select * from date_test 
  where date_in_date >= to_date('06/22/2017', 'MM/DD/YYYY')  
    and date_in_date <  to_date('06/22/2017', 'MM/DD/YYYY') + 1;

案例2:

 select * from date_test where date_in_varchar like '06/22/2017%'

答案 2 :(得分:0)

经过一些研究后,我采用了以下方法:

案例1:正确存储的日期(日期类型)

SELECT * FROM date_test 
WHERE TRUNC(date_in_date)= to_date('06/22/2017', 'MM/DD/YYYY', 'nls_date_language = ENGLISH');

案例2:日期存储为varchars

SELECT * FROM date_test
WHERE TRUNC(TO_DATE(date_in_varchar, 'MM/DD/YYYY HH:MI:SS AM')) = to_date('06/22/2017', 'MM/DD/YYYY', 'nls_date_language = ENGLISH');