gpt4 book ai didi

tsql - Sql - 基于日期的列检查约束

转载 作者:行者123 更新时间:2023-12-05 00:55:58 28 4
gpt4 key购买 nike

这不是 Check constraint on date 的副本但我可能错过了另一个类似的问题。

在 MS SQL 上,您可以创建以下约束:

ALTER TABLE [X] WITH CHECK ADD CONSTRAINT [CCCHK03_TBX] CHECK
(
[TBX_YEAR] = DATEPART( year, GetDate() )
)

您可以很好地插入记录,但我无法完全测试其含义,当服务器日期超过 2017 年时会发生什么?我的印象是它允许插入 2017 年,但理论上它会使 2016 年的所有记录无效。

这个表是一个仅插入表,所以记录永远不会更新,所以这不是问题。我主要关心的是是否有可能由此导致的服务器稳定性问题?

我似乎找不到与此相关的任何内容,但 MS 必须有理由允许这种限制。

通常我会建议创建一个插入触发器并检查它,但这让我很好奇。

编辑: 来自目标数据答案的扩展测试:
IF ( OBJECT_ID( 'tempdb..#CheckTest' ) IS NOT NULL )
DROP TABLE #CheckTest
GO

CREATE TABLE #CheckTest ( MN INT )
ALTER TABLE #CheckTest WITH CHECK ADD CONSTRAINT CHK_MN CHECK ( MN = DATEPART( SECOND, GETDATE() ) )
ALTER TABLE #CheckTest CHECK CONSTRAINT CHK_MN
GO

-- Control Test. This will fail with:
--Msg 547, Level 16, State 0, Line 12
--The INSERT statement conflicted with the CHECK constraint "CHK_MN". The conflict occurred in database "tempdb", table "dbo.#CheckTest", column 'MN'.
--The statement has been terminated.
INSERT INTO #CheckTest ( MN )
VALUES ( DATEPART( SECOND, DATEADD( SECOND, 5, GETDATE() ) ) )

-- Add 5 different seconds.
DECLARE @Counter int = 0;

WHILE @Counter < 5
BEGIN
INSERT INTO #CheckTest ( MN )
VALUES ( DATEPART( SECOND, GETDATE() ) )

SET @Counter += 1;

-- Delay for a second.
WAITFOR DELAY '00:00:01';
END
GO

-- Add a different second.
-- Disabling and Enabling a check will work just fine so long as the check already exists.
ALTER TABLE #CheckTest NOCHECK CONSTRAINT CHK_MN;
INSERT INTO #CheckTest ( MN )
VALUES ( DATEPART( SECOND, DATEADD( SECOND, 5, GETDATE() ) ) )
ALTER TABLE #CheckTest CHECK CONSTRAINT CHK_MN;

-- Control Test. This will fail with:
--Msg 547, Level 16, State 0, Line 12
--The INSERT statement conflicted with the CHECK constraint "CHK_MN". The conflict occurred in database "tempdb", table "dbo.#CheckTest", column 'MN'.
--The statement has been terminated.
INSERT INTO #CheckTest ( MN )
VALUES ( DATEPART( SECOND, DATEADD( SECOND, 5, GETDATE() ) ) )
GO

-- Check table contents.
SELECT * FROM #CheckTest;
GO

-- Dropping and recreating the check constraint will result in an error:
--Msg 547, Level 16, State 0, Line 37
--The ALTER TABLE statement conflicted with the CHECK constraint "CHK_MN". The conflict occurred in database "tempdb", table "dbo.#CheckTest", column 'MN'.
ALTER TABLE #CheckTest DROP CONSTRAINT CHK_MN;
ALTER TABLE #CheckTest WITH CHECK ADD CONSTRAINT CHK_MN CHECK ( MN = DATEPART( SECOND, GETDATE() ) )
GO

DROP TABLE #CheckTest
GO

编辑 2: 摘要

根据测试和反馈,虽然它确实是一个有趣的练习,而且绝对看起来是 100% 完全有效的,但我绝对会纯粹从“面向 future ”的角度建议不要这样做,因为支票永远不可能改变了。我个人认为基于触发器的约束将是最易于维护的。

最佳答案

好问题!

简短的回答是你会没事的。仅在检查中插入或更新列时才验证检查。您现有的记录不会受到年份变化的影响。

但是,您应该考虑一些潜在的问题。这种类型的检查会使您更难修改表设计,尤其是通过 SSMS(这往往会创建一个新表,从旧表导入数据,删除旧表并重命名新表)。导入将失败,因为旧记录与当前约束规则不匹配。当然你仍然可以使用 tSQL 进行修改。

修改表

-- Disable check.
ALTER TABLE [Schema].[Table] NOCHECK CONSTRAINT [Check];

-- Makes changes here.

-- Enable check.
ALTER TABLE [Schema].[Table] CHECK CONSTRAINT [Check];

更新表中的其他列时,您不需要禁用检查。

测试查询

多年来,测试有点困难,所以我换成了分钟。
CREATE TABLE #CheckTest 
(
MN INT CONSTRAINT CHK_MN CHECK (MN = DATEPART(MINUTE, GETDATE()))
)
;

-- Add two different minutes.
WHILE @COUNTER < 2
BEGIN

INSERT INTO #CheckTest
(
MN
)
VALUES
(DATEPART(MINUTE, GETDATE()))
;

SET @COUNTER = @COUNTER + 1;

-- Delay for a minute.
WAITFOR DELAY '00:01:00'
END

-- Check table contents.
SELECT
*
FROM
#CheckTest
;

关于tsql - Sql - 基于日期的列检查约束,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37181732/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com