我有一个简单的表,我必须在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');
那么,在上述案例中比较日期最安全的方法是什么?
答案 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');