SQL 制約により、データが妥当性基準を満たすように強制される可能性があることを私は知っています。しかし、「学生の成績は、'finalized' フラグが false の場合にのみ更新できます」などの基準はどうでしょうか。このような更新基準は、アプリケーションで処理する必要がありますか?
3 に答える
簡単な回答: いいえ、SQL 制約自体は、Finalized が「true」の場合、列 Grade の変更を防ぐことはできません (ただし、それ以外の場合は変更を許可します)。
SQL 制約にはいくつかの種類があります。CHECK、DEFAULT、NOT NULL、UNIQUE、主キー、および外部キーです。
これらはそれぞれ、単独または組み合わせて、列の値を制限または影響を与えることができますが、許可されている値への UPDATE を防ぐことはできません。特に、これらの制約のいずれも、Grade および Finalized の以前の値に基づいて、Grade および/または Finalized への UPDATE を防ぐことはできません。
UPDATE トリガーはこれを行うことができます: Grade の新しい値と古い値を比較し、これらが異なり、Finalized = 'true' の場合、UPDATE をロールバックし、説明的なエラー メッセージを表示します。
ただし、アプリケーションはそのような「ビジネス ルール」をより適切に適用できますし、適用する必要があります。ルール自体は、Finalized 値をいつ変更できるかについて少し明確にすることができます。たとえば、Grade の変更と Finalized = 'false' の設定を同時に行うことはできますか? トリガー ロジックはそのような詳細を処理できます。アプリケーション (フロントエンド/ミドルウェア/バックエンド) のどこかでルールを明示しながら、それをフェイルセーフとしてインストールすることは合理的です。
トリガー、制約、および追加の列。
最後から始めて:
追加の列には、「固定」される値が格納されます。
ALTER TABLE ADD SavedGrade int
制約は、
Grade
列の変更を制限します。ALTER TABLE Students ADD CONSTRAINT CK_Grade CHECK (Finalised = 'false' OR Grade = SavedGrade)
列が更新されると、トリガーは追加の列
Grade
を更新します (以下は SQL Server の場合です)。CREATE TRIGGER StudentsFinaliseGrade ON Students AFTER INSERT, UPDATE AS IF UPDATE(Grade) UPDATE Students SET SavedGrade = i.Grade FROM inserted i WHERE i.ID = Students.ID AND i.Grade <> i.SavedGrade
そのため、 である限りFinalised = 'false'
、Grade
列は変更される可能性があります。変更されると、値はすぐにSavedGrade
列に格納されます。SavedGrade
(そうしないと、制約によって に設定できないため、直接更新しています。) が設定Finalised
されると'true'
すぐに、制約のために列をFinalised
変更できなくなります。Grade
IMO、実際の制約としてではなく、アプリケーションまたはストアドプロシージャ(おそらく両方)で実行する必要があると思います(とりわけ、特定の例では、成績が「確定」されているとは限りませんそれは実際には最終的なものです)。
ただし、これを制約として実装する場合は、CHECK 制約を使用します (再度、例を使用します)。
CONSTRAINT chk_grade CHECK(grade between 0 AND 100 and finalized = 0)
その特定の構文を確認してください。ただし、ここから始めます。