2009-09-01 34 views
3

我正在使用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 

... HM,我不能相信它是否是唯一的方法解決有問題,所以我想問一問:如何以最佳方式解決此問題?

在此先感謝。


UPD 2014:
另見Storing partial dates in a database

+0

你爲什麼不知道完整的日期?沒有完整日期的日期字段有什麼用? – HLGEM 2009-09-01 13:15:44

+0

有時日期的某一天是真正未知的。例如,我可以填寫稀有未公開的音樂演示記錄,但該記錄可能是錯誤的或部分日期不記錄當天的記錄。所以我想保留延期填寫記錄信息的可能性 – 2009-09-01 13:34:56

回答

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 
+0

謝謝,KM,我會考慮你的解決方案 – 2009-09-01 13:40:12

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()) 

希望這有助於!

+0

謝謝你的回覆,埃裏克。我現在正好看看你的建議 – 2009-09-01 13:37:34

2

您是否考慮將您的月份,日期和年份存儲在單獨的列中?這將是一個非常簡單的方法,但有時候這是要走的路。這將允許您輕鬆查詢特定月份和/或日期的值,而無需進行大量的類型轉換,這可能會混淆掉可能需要在代碼中處理代碼的其他人。

+1

我通常不會推薦這個,但是如果你不知道這一天,我沒有看到如果沒有可怕的操縱,該怎麼做。如果三個字段中的一個被更改並且只有三個字段構成有效日期,您纔可以添加從觸發器填充的實際日期字段。然後,如果您有有效的日期,則可以使用 日期函數進行查詢(如果需要的話)。 – HLGEM 2009-09-01 13:14:21