Как частично сохранить значения даты? - PullRequest
3 голосов
/ 01 сентября 2009

Я использую 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:
Также см. Хранение частичных дат в базе данных

Ответы [ 3 ]

2 голосов
/ 01 сентября 2009

Рассматривали ли вы хранение вашего месяца, дня и года в отдельных столбцах? Это был бы очень простой и упрощенный подход, но иногда это путь. Это позволит вам легко запрашивать значения для определенного месяца и / или дня без большого количества преобразований типов, которые могут сбить с толку кого-то другого, кому, возможно, потребуется работать над кодом в будущем.

2 голосов
/ 01 сентября 2009

здесь вы можете сохранить каждую часть даты, и при этом ограничить их действительной датой:

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
1 голос
/ 01 сентября 2009

Умные ключи даты - определенно лучший способ. Однако ваш код немного длинный, поскольку 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())

Надеюсь, это поможет!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...