如何部分存储日期值?

时间:2009-09-01 12:31:15

标签: sql sql-server sql-server-2005 datetime

我正在使用MS SQL Server 2005,我需要部分存储日期值。例如,日期的某一部分实际上可能仍然未知,但MS SQL Server约束指定完整日期,如下所示:

INSERT foo(dt) VALUES('2001-10-31');

我想使用这样的东西:

INSERT foo(dt) VALUES ('2001-10-??');

当然,MS SQL无法接受这样的日期,我发现了一个将日期部分转换为乘数的粗略示例:

SET NOCOUNT ON 
CREATE TABLE foo ( 
    dt INT 
) 
INSERT foo VALUES ( 
    DATEPART(YEAR, GETDATE()) * 10000 
        + DATEPART(MONTH, GETDATE()) * 100 
        + DATEPART(DAY, GETDATE()) 
) 
SELECT dt FROM foo 
DROP TABLE foo

......嗯,我无法相信这是否是解决问题的唯一方法,所以我想问:我如何以最佳方式解决这个问题?

提前致谢。


UPD 2014:
另请参阅Storing partial dates in a database

3 个答案:

答案 0 :(得分:2)

您是否考虑过将您的月,日和年存储在不同的列中?这将是一个非常rudimentart&简单的方法,但有时这是要走的路。这样,您就可以轻松查询特定月份和/或日期的值,而无需进行大量类型转换,这些转换可能会使可能需要处理其他代码的其他人感到困惑。

答案 1 :(得分:2)

在这里,您可以存储每个日期部分,并将它们限制在有效日期:

CREATE Table PartialDates
(
     YearPart       smallint --(2 bytes -32k to +32k)
    ,MonthPart      tinyint  --(1 byte 0 to 255)
    ,DayPart        tinyint  --(1 byte 0 to 255)
    ,CompleteDate  AS (CONVERT(datetime,CONVERT(varchar(10),YearPart)+'-'+CONVERT(varchar(10),MonthPart)+'-'+CONVERT(varchar(10),coalesce(DayPart,1))))
)
ALTER TABLE dbo.PartialDates ADD CONSTRAINT
    CK_PartialDates_IsDate CHECK (ISDATE(CONVERT(varchar(10),YearPart)+'-'+CONVERT(varchar(10),MonthPart)+'-'+CONVERT(varchar(10),coalesce(DayPart,1)))=1)
GO

insert into PartialDates (yearpart,monthpart,daypart) values(2009,91,1) --error
insert into PartialDates (yearpart,monthpart,daypart) values(2009,1,1)  --ok
insert into PartialDates (yearpart,monthpart,daypart) values(2009,1,51) --error
insert into PartialDates (yearpart,monthpart,daypart) values(2009,2,29) --error
insert into PartialDates (yearpart,monthpart,daypart) values(2009,2,28) --ok
insert into PartialDates (yearpart,monthpart,daypart) values(2009,2,null)--ok

select * from PartialDates

YearPart MonthPart DayPart CompleteDate
-------- --------- ------- -----------------------
2009     1         1       2009-01-01 00:00:00.000
2009     2         28      2009-02-28 00:00:00.000
2009     2         NULL    2009-02-01 00:00:00.000

(3 row(s) affected

答案 2 :(得分:1)

智能日期键肯定是要走的路。但是,您的代码有点长,因为SQL Server使用convert提供了快速获取代码的方法:

select cast(convert(varchar, GETDATE(), 112) as int)

您会认为convert可以直接int,但它不起作用。因此,您必须转换为varchar,然后转换为int

如果您希望当天为00,请代替实际日期:

select cast(convert(varchar, getdate(), 112) as int) - day(getdate())

希望这有帮助!