Sql-Server-2005
SQL Server 2005 - 將日期時間欄位約束為日期的最佳方法
然而:
從 SQL Server 2008 開始的日期欄位類型
給定一張桌子:
CREATE TABLE dbo.MyTable ( Code int NOT NULL, DateCode datetime NOT NULL ) CONSTRAINT [PK_MyTable] PRIMARY KEY CLUSTERED ( [Code] ASC, [DateCode] DESC );
約束 DateCode 只是一個日期的最佳方法是什麼?
它必須允許沒有時間部分的日期。
2017-01-02 2017-01-02 00:00:00.000 20170102
現在我正在使用:
ALTER TABLE dbo.MyTable ADD CONSTRAINT [CHK_MyTable_DateCode] CHECK ([DateCode] = DATEADD(DAY, 0, DATEDIFF(DAY, 0, [DateCode])));
但是,我想知道是否有最好/最短的方法來完成它。
您可以稍微簡化一下,因為 SQL Server 知道
datetime
它可以將該值視為自 0 以來的天數。我更喜歡使用'19000101'
大於零的值,因為發生的事情稍微不那麼神秘:ALTER TABLE dbo.MyTable ADD CONSTRAINT CHK_MyTable_DateCode CHECK (DateCode = DATEDIFF(DAY, '19000101', DateCode));
但是,我發現責罵那些可能使用他們沒有意識到包含時間組件的內置
GETDATE()
函式或參數的使用者是一個奇怪的選擇。@OrderDate
因此,解決此問題的一種更簡潔的方法是使用觸發器:CREATE TRIGGER dbo.MyTable_RoundCodeDate ON dbo.MyTable INSTEAD OF INSERT AS BEGIN SET NOCOUNT ON; INSERT dbo.MyTable(Code, DateCode) SELECT Code, DATEDIFF(DAY, '19000101', DateCode) FROM inserted; END GO
這裡的一些人不喜歡使用
INSTEAD OF
觸發器,但我認為在插入之前按摩這些值比在插入之後更好。PK 的處理方式與沒有觸發器的情況相同 - 仍然會在插入時擷取違規(但是,使用後觸發器,您不會在觸發器程式碼執行之前遇到違規,理論上這至少意味著更多的日誌記錄)。實際上,您可以GROUP BY
在觸發器中添加一個以靜默忽略源語句中的重複項,例如INSERT ... VALUES(1,GETDATE()), (1,CURRENT_TIMESTAMP);
.