【问题标题】:Adding CHECK constraint conflicts with IS NULL添加 CHECK 约束与 IS NULL 冲突
【发布时间】:2013-10-16 07:44:52
【问题描述】:

当我尝试向其中一个表添加约束时遇到问题。我想检查一个函数,使状态为真,然后根据它是否为真返回 1 或 0。但在函数中,我检查列中的值是否为 NULL 并导致错误

ALTER TABLE 语句与 CHECK 约束“chk_StateFinished”冲突。数据库“databaseName”、表“dbo.Participation”中发生冲突。

函数看起来像这样

CREATE FUNCTION CheckStateFinished(@StudentID varchar(10), @CourseID varchar(10), @CoursePeriod varchar(10), 
                       @SchoolYear int, @State varchar(15)) RETURNS int
AS BEGIN 
    DECLARE @Grade varchar(1)
    SELECT @Grade = Grade FROM Participation WHERE  StudentID = @StudentID AND CourseID = @CourseID AND CoursePeriod = @CoursePeriod AND SchoolYear = @SchoolYear
    RETURN CASE WHEN @State = 'Avslutad' AND @Grade = 'U' OR @Grade IS NULL THEN 0
                ELSE 1
    END
END

添加检查约束如下所示:

ALTER TABLE Participation ADD CONSTRAINT chk_StateFinished CHECK (dbo.CheckStateFinished(StudentID, CourseID, CoursePeriod, SchoolYear, _State) = 1) 

我应该怎么做而不是函数中的 IS NULL 还是应该做其他事情?

【问题讨论】:

    标签: sql tsql check-constraints


    【解决方案1】:

    问题不在于 CheckStateFinished 函数,而在于要添加 CHECK CONSTRAINT 的表 Participation 中的现有数据。默认情况下,当我们使用 Alter table 命令将检查约束添加到现有表时,它适用于现有数据和任何新数据。 表 Participation 中可能有一些行,对于给定的 StudentID、CourseID、CoursePeriod、SchoolYear,_State 参数函数评估为 0,因此检查约束失败。

    在这种情况下,请使用 WITH NOCHECK 选项,以便检查约束仅适用于新数据。

     create table Participation (Grade varchar(1),StudentID varchar(10), CourseID varchar(10), CoursePeriod varchar(10), SchoolYear int, [State] varchar(15))
    
        insert into Participation values ('A','Student1','Course1','CourseP1',2013,'Avslutad')
    -- for this row check constraint will work fine.
        insert into Participation values ('U','Student2','Course1','CourseP1',2013,'Avslutad') -- for this row check constraint will fail.
        insert into Participation values (NULL,'Student3','Course1','CourseP1',2013,'Avslutad')
    -- for this row check constraint will fail.
        insert into Participation values ('U','Student4','Course1','CourseP1',2013,'XYZ')
    -- for this row check constraint will work fine.
        --insert into Participation values ('A','Student5','Course1','CourseP1',2013,'XYZ')
        Go
    
    CREATE FUNCTION CheckStateFinished(@StudentID varchar(10), @CourseID varchar(10), @CoursePeriod varchar(10), 
                           @SchoolYear int, @State varchar(15)) RETURNS int
    AS BEGIN 
        DECLARE @Grade varchar(1)
        SELECT @Grade = Grade FROM Participation WHERE  StudentID = @StudentID AND CourseID = @CourseID AND CoursePeriod = @CoursePeriod AND SchoolYear = @SchoolYear
        RETURN CASE WHEN @State = 'Avslutad' AND @Grade = 'U' OR @Grade IS NULL THEN 0
                    ELSE 1
        END
    END
    
    Go                
    
    ALTER TABLE Participation WITH NOCHECK  -- add this and your constraint will work.
    ADD CONSTRAINT chk_StateFinished CHECK (dbo.CheckStateFinished('Student3','Course1','CourseP1',2013,'Avslutad') = 1) 
    
    Go
    

    【讨论】:

    • 非常感谢它总是那些你看不到的简单的东西。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-13
    • 1970-01-01
    • 2021-08-04
    • 2014-08-16
    • 1970-01-01
    • 2021-12-11
    相关资源
    最近更新 更多