1

テーブルの 1 つに制約を追加しようとすると、問題が発生しました。状態が true になるように関数をチェックインし、true かどうかに応じて 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 の代わりに何をすべきか、または何か他のことをする必要がありますか?

4

1 に答える 1

3

問題は関数 CheckStateFinished ではなく、CHECK CONSTRAINT が追加されるテーブル Participation 内の既存のデータにあります。デフォルトで Alter table コマンドを使用して既存のテーブルにチェック制約を追加すると、既存のデータと新しいデータの両方に適用されます。テーブル Participation に、特定の 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
于 2013-10-16T09:36:54.070 に答える