添加CHECK约束与IS NULL冲突

时间:2013-10-16 07:44:52

标签: sql tsql check-constraints

当我尝试向其中一个表添加约束时出现问题。我想检查一个函数,以便状态为真,然后返回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

Add Check Constraint如下所示:

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

我应该怎么做而不是函数中的IS NULL,或者我应该做些什么呢?

1 个答案:

答案 0 :(得分:3)

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

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

 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