SQL Server 2005 - 将日期时间字段约束为日期的最佳方法

McN*_*ets 5 sql-server-2005 constraint datetime

然而:

以 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
);
Run Code Online (Sandbox Code Playgroud)

约束 DateCode 只是一个日期的最佳方法是什么?

它必须允许没有时间部分的日期。

2017-01-02
2017-01-02 00:00:00.000
20170102
Run Code Online (Sandbox Code Playgroud)

现在我正在使用:

ALTER TABLE dbo.MyTable ADD CONSTRAINT [CHK_MyTable_DateCode]
    CHECK ([DateCode] = DATEADD(DAY, 0, DATEDIFF(DAY, 0, [DateCode])));
Run Code Online (Sandbox Code Playgroud)

但是,我想知道是否有最好的/简短的方法来完成它。

Aar*_*and 3

您可以稍微简化一下,因为 SQL Server 知道datetime它可以将该值视为自 0 以来的天数。我更喜欢使用'19000101'大于零的值,因为它稍微不那么神秘:

ALTER TABLE dbo.MyTable
ADD CONSTRAINT CHK_MyTable_DateCode
CHECK (DateCode = DATEDIFF(DAY, '19000101', DateCode));
Run Code Online (Sandbox Code Playgroud)

然而,我发现责骂那些可能使用内置函数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
Run Code Online (Sandbox Code Playgroud)

使用INSTEAD OF触发器在这里的一些人中并不受欢迎,但我认为在插入之前调整这些值比插入之后更好。PK 的处理方式与没有触发器的情况相同 - 违规行为仍然会在插入时被捕获(但是,使用后触发器,直到触发代码运行之后才会遇到违规行为,这在理论上至少意味着更多的日志记录)。事实上,您可以GROUP BY向触发器添加 a 以静默忽略源语句中的重复项,例如INSERT ... VALUES(1,GETDATE()), (1,CURRENT_TIMESTAMP);