Question

I got a problem when I try to add a constraint to one of my tables. I want to check in a function so that a state is true and then returns 1 or 0 depending on if it is true. But in the function I check if a value in a column is NULL and that causes the error

The ALTER TABLE statement conflicted with the CHECK constraint "chk_StateFinished". The conflict occurred in database "databaseName", table "dbo.Participation".

the Function looks like this

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

And the Add Check Constraint looks like this:

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

What should I do instead of IS NULL in the Function or should i do something else?

Was it helpful?

Solution

The issue is not in function CheckStateFinished but with existing data in table Participation on which CHECK CONSTRAINT is to be added. When we add Check constraint to an existing table using Alter table command by default it applies to both existing data and any new data. There might be some row in table Participation where for given StudentID, CourseID, CoursePeriod, SchoolYear, _State parameters function is evaluating to 0 and hence Check constraint is getting failed.

In such a case use WITH NOCHECK option so that Check constraint applies only to new data.

 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
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top