2017-03-07 142 views
0

我有一个具有LETTER_SENT日期字段的Oracle表。 LETTER_SENT是一个varchar2字段,并且是一个yyyymmdd文本字符串(所以20140708表示这封信是在2014年7月8日发送的)。注意:这不是我的表,我只有授予SELECT的权利,所以我不能强制它为yyyymmdd日期。在VARCHAR2是日期的VARCHAR2字段上使用索引

通常,我需要查找在一系列日期中发送的信件。通常,我在WHERE IN('开始日期',...,'结束日期')​​。根据我对SQL的理解,以这种方式进行操作并不会以任何方式修改该字段,而不会影响索引的使用(而转换为日期或数字,然后进行比较会影响索引)。

表现明智,这很好。然而,有时我的日期范围很大,并且有一个巨大的IN,... OR IN,...或WHERE语句中的IN子句很丑陋。

当日期是一个索引varchar2时,还有另外一个语法更漂亮,但仍然有效的方法来在where子句(date_begin和date_end之间的日期比较)中进行日期比较吗?

+0

您是否尝试过'letter_sent> ='20160101'和letter_sent <='20160430''?我想知道包含这些数字的索引字符串如何提取数据。也许它是高性能的 - 我不知道。只是好奇,如果你已经尝试过。 – zedfoxus

+0

@zedfoxus这个工程好得多 - 我不相信我忘了这个作品!请张贴这个答案,让我可以upvote和接受它,砸我的头,我忘了这一点。 – Joe

+2

Tom Kyte有一个非常令人信服的会议演示文稿(我在OTN上的一个主题中看到了一个链接) - 他展示了一个具体的例子,说明应该对日期进行编码的'VARCHAR2'列的索引与索引'DATE'列 - 用于完全相同的数据(除了此列的不同数据类型外)。不要在日期中使用'VARCHAR2';这是超过100个优秀原因之一。 – mathguy

回答

0

既然你对VARCHAR2的一个索引,我相信,你将能够使用查询,像这样:

select * from tablename 
where letter_sent >= '20160101' and letter_sent <= '20160430' 

文本可以按顺序处理的,你可能会得到期望的结果使用索引。

长期来看,创建letter_sent_date作为日期字段会更有效,请使用letter_sent中的数据更新此字段,然后贬低letter_sent。您将从使用以日期为中心的函数(如year(letter_sent_date))中获益,而不需要将varchar2字段转换为日期,然后应用函数。

+0

@Joe - 也会有无数的其他好处。想象一下,如果日期是在'varchar2'数据类型中,确定后续信函是否在最初的10个工作日内发送是多么容易! – mathguy

+0

很高兴知道为什么答案收到downvote。我想知道这个答案是否可以改进。 – zedfoxus

+0

因为鼓励“不良行为”而被低估。客户应该使用正确的数据类型。见下面的答案。另请参阅我的评论/上面的例子,为什么这是不好的。 – BobC

2

正确的方法是使用DATE数据类型而不是VARCHAR2()来存储LETTER_SENT。在语法,索引的使用,结果的正确性,优化器的统计数据以及最终的性能方面,你会好得多。

+0

相信我,我知道 - 这不是我的桌子:/。我不知道为什么桌子创作者选择这样做。我将编辑原件以反映这一点。无论如何,upvoting所以任何人后来看到如何不这样做:) – Joe

+0

@Joe。我**高度**鼓励你回到桌子的创作者身上并修正这个问题。因为这个原因,我失去了升级的次数。另外,由于类型转换,您将隐式禁用Oracle优化。任何创作者拒绝;去他们的经理! – BobC

+1

我会提及给他们,但我不希望有任何改变。大公司移动冰河,并没有改变。 – Joe

相关问题