1

当我尝试向我的一个表添加约束时遇到问题。我想检查一个函数,以便状态为真,然后根据它是否为真返回 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 还是应该做其他事情?

4

1 回答 1

3

问题不在函数 CheckStateFinished 中,而是在要添加 CHECK CONSTRAINT 的表 Participation 中的现有数据中。默认情况下,当我们使用 Alter table 命令将检查约束添加到现有表时,它适用于现有数据和任何新数据。对于给定的 StudentID、CourseID、CoursePeriod、SchoolYear、_State 参数函数,表 Participation 中可能有一些行正在评估为 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
于 2013-10-16T09:36:54.070 回答