Triggers SQL Server 2012检查约束在UPDATE或DELETE语句上未触发

Triggers SQL Server 2012检查约束在UPDATE或DELETE语句上未触发,triggers,sql-server-2012,check-constraints,Triggers,Sql Server 2012,Check Constraints,我正在尝试对一个表执行数据验证,需要跨多个行和列进行检查。基本上,我希望确保对于任何给定的工具,至少存在一个标记为活动版本或Beta版本的版本 我认为检查这一点的唯一方法是通过用户定义的标量函数和调用该函数的check约束。我能够创建一个函数,返回我期望的结果(如果可以,返回0;如果不可以,返回1),它可以工作。。。但仅在插入的上。当我执行UPDATE或DELETE语句时,check约束不会失败,因此无论哪种情况,我最终都会得到错误的数据 下面是我正在使用的表和函数的示例 CREATE TABL

我正在尝试对一个表执行数据验证,需要跨多个行和列进行检查。基本上,我希望确保对于任何给定的工具,至少存在一个标记为活动版本或Beta版本的版本

我认为检查这一点的唯一方法是通过用户定义的标量函数和调用该函数的
check
约束。我能够创建一个函数,返回我期望的结果(如果可以,返回0;如果不可以,返回1),它可以工作。。。但仅在插入的
上。当我执行
UPDATE
DELETE
语句时,check约束不会失败,因此无论哪种情况,我最终都会得到错误的数据

下面是我正在使用的表和函数的示例

CREATE TABLE VersionTest(VersionID int NOT NULL, ToolID int NOT NULL, IsActiveVersion bit NOT NULL, IsBetaVersion bit NOT NULL)
GO

ALTER TABLE VersionTest ADD  CONSTRAINT [DF_VersionTest_IsActiveVersion]  DEFAULT ((0)) FOR [IsActiveVersion]
GO

ALTER TABLE VersionTest ADD  CONSTRAINT [DF_VersionTest_IsBetaVersion]  DEFAULT ((0)) FOR [IsBetaVersion]
GO

CREATE FUNCTION fn_ValidateVersionTest(@toolID int) RETURNS SMALLINT
AS
      BEGIN
      IF (@toolID = -1)
        BEGIN
          RETURN 0
        END
      ELSE
        BEGIN
            IF EXISTS (SELECT 1
                       FROM VersionTest
                       WHERE ToolID = @toolID
                       GROUP BY ToolID, IsActiveVersion, IsBetaVersion
                       HAVING (SUM(CASE WHEN IsActiveVersion = 1 THEN 1 ELSE 0 END) + 
                               SUM(CASE WHEN IsBetaVersion = 1 THEN 1 ELSE 0 END)) > 0)
              RETURN 0
        END
        RETURN 1      
    END
GO

ALTER TABLE VersionTest WITH CHECK ADD  CONSTRAINT [CK_VersionTest] CHECK  (([dbo].[fn_ValidateVersionTest]([ToolID])=(0)))
GO
ALTER TABLE VersionTest CHECK CONSTRAINT [CK_VersionTest]
GO
下面的INSERT语句工作得很好

INSERT INTO VersionTest (ToolID, VersionID, IsActiveVersion, IsBetaVersion)
VALUES (1, 1, 1, 0)

INSERT INTO VersionTest (ToolID, VersionID, IsActiveVersion, IsBetaVersion)
VALUES (1, 2, 0, 0)
正如预期的那样,此INSERT语句失败:

INSERT INTO VersionTest (ToolID, VersionID, IsActiveVersion, IsBetaVersion)
VALUES (2, 1, 0, 0)
但是,以下UPDATE和DELETE语句并没有在我预期的情况下失败:

UPDATE VersionTest 
SET IsActiveVersion = 0, IsBetaVersion = 0
WHERE VersionID = 1

DELETE VersionTest WHERE VersionID = 1

我还有别的办法吗?我必须使用触发器吗

我们可以通过这种方式强制检查更新。
假设你有一张这样的桌子

create table UserTest(Id int, IsEnabled bit, [GroupId] int)
现在,我们要检查
[GroupId]
只启用了1个用户

通常约束看起来像

ALTER TABLE [dbo].[UserTest] ADD CONSTRAINT CHK_OnlyOneEnabled  CHECK (dbo.checkOnlyOne(GroupId)=1)
在您更新
GroupId

因此,我们必须强制约束通过执行以下操作来验证IsEnabled列

ALTER TABLE [dbo].[UserTest] ADD CONSTRAINT CHK_OnlyOneEnabled  CHECK (dbo.checkOnlyOne(GroupId, IsEnabled )=1)

无论是否在函数中使用IsEnabled值。

请参阅“请停止梳理检查约束和自定义项”。看起来像我的场景,即使函数不使用它,也必须传递额外的参数