SQL将Int转换为Date或Char

时间:2012-10-19 15:24:53

标签: sql sql-server-2008

我的dbase具有6位数的日期格式,带有int数据类型('734503'= 01/01/2012)。 我已经能够成功地将这些转换为char:

SELECT CONVERT(char(12),dateadd(dd,(date_paid -    639906),'1/1/1753'),101)  
FROM   vouchers       
WHERE date_paid =    '734503'

这给了我01/01/2012的输出。 但是,如果我在这样的查询中搜索转换日期:

SELECT CONVERT(char(12),dateadd(dd,(date_paid - 639906),'1/1/1753'),101) 
FROM vouchers    
WHERE date_paid >= '09/01/2012'  AND date_paid <= '09/30/2012'

为什么不进行转换?即使我在date_paid字段的WHERE语句中使用CONVERT,它不应该在那里工作吗?

我想我的问题是如何使用转换后的字符日期进行搜索而不必使用6位数日期?

2 个答案:

答案 0 :(得分:1)

您的问题是您正在将INT列与STRING值进行比较,并期望它像解析日期一样解决...

WHERE date_paid >= '09/01/2012'
  AND date_paid <= '09/30/2012' 

-- date_paid is an INT (according to your question)
-- '09/01/2012' is a STRING

由于数据类型不同,因此存在 隐式 CAST()。你有效地做了......

WHERE CAST(date_paid AS VARCHAR(10)) >= '09/01/2012'
  AND CAST(date_paid AS VARCHAR(10)) <= '09/30/2012' 

-- NOTE:  All of these values are now strings
--        They may LOOK like dates, but they're just strings

您真正需要做的是 显式地 将字符串操作为整数。

WHERE date_paid >= DATEDIFF(DAY, '01/01/1753', '09/01/2012') + 639906
  AND date_paid <= DATEDIFF(DAY, '01/01/1753', '09/30/2012') + 639906

这也涉及隐式演员表。 DATEDIFF()只接受DATETIME数据类型,因此首先将字符串隐式地转换为DATETIME。

修改

另一种选择是将date_paid字段CAST()转换为DateTime,然后将WHERE caluse置于其上。这里的缺点是......
   - 必须在每一行上完成CAST(),然后应用WHERE子句    - 这可以防止任何索引的使用并显着降低性能

上面的答案对常量值进行了所有操作,以便搜索到的字段可以在其原生状态下处理;因此允许使用索引。

答案 1 :(得分:1)

首先,如果可以,请更改数据库架构。 date_paid列的数据类型应该是datetimedate,而不是&#39; int&#39;或者&#39; char`。

...但是如果您遇到此架构,那么您的date_paid值似乎是整数,其值693596代表1 jan 1900。 (此日期是SQL Server零值映射到的位置。)因此,您需要做的就是移动或将搜索值偏移此量。

假设您要搜索的日期是今天,2012年10月19日

 Declare @SearchDate DateTime = '20 Oct 2012'

然后将您的查询谓词写为:

  Select * From vouchers
  Where date_paid = DateDiff(day, 0, @searchDate) + 693596 

确保构建查询,以便所有处理或计算都在date_paid列的等号的其他侧完成(如我的示例所示)。这样查询处理器可以使用date_Paid上的索引(如果存在)。如果查询在date_Paid上有任何函数调用或其他计算,则查询必须读取整个表,并且不能使用其他可用的索引请参阅SARGable

顺便说一下,我很好奇这个设计(这个大的整数用于表示日期)来自哪里,我注意到这个值恰好等于1900 * 365,这意味着在这方案,零值重新设置在零年1月1日(当基督出生时),这将很酷,除了你不能在SQL Server日期使用它因为SQL Server值表示日期为16位签名整数,将零映射到1900年1月1日,并限制为16位整数(-16,384)中的最小值,相当于1753年左右的某个日期。