1

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

我认为检查这一点的唯一方法是通过用户定义的标量函数和CHECK调用该函数的约束。我能够创建返回我期望的函数(如果正常,则为 0,如果不正常,则为 1)并且它可以工作......但只能INSERT. 当我执行UPDATEorDELETE语句时,检查约束不会失败,因此在任何一种情况下我都会得到错误的数据。

这是我正在使用的表格和函数的示例。

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

我应该这样做吗?我必须使用触发器吗?

4

1 回答 1

2

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

create table UserTest(Id int, IsEnabled bit, [GroupId] int)

现在,我们要检查只有 1 个用户被启用[GroupId]

通常约束看起来像

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 值。

于 2015-09-07T18:23:00.640 回答