私のスキーマにはID1
、ID2
、 の3 つの列があります。Status
上記の各列は文字列です。
次の制約を作成したいと思います。
ID1
同じ値を持ちID2
、「未処理」状態のレコードが複数存在することはできません。同じレコードでUNPROCESSED 状態でないレコードが複数あっても問題ID1
ありません。ID2
SQL Server でこれを行うことは可能ですか?
私のスキーマにはID1
、ID2
、 の3 つの列があります。Status
上記の各列は文字列です。
次の制約を作成したいと思います。
ID1
同じ値を持ちID2
、「未処理」状態のレコードが複数存在することはできません。同じレコードでUNPROCESSED 状態でないレコードが複数あっても問題ID1
ありません。ID2
SQL Server でこれを行うことは可能ですか?
SQL Server 2008 以降を使用していると仮定すると、フィルター選択されたインデックスを適用できます。
CREATE UNIQUE INDEX UQ_Unprocessed_IDs ON UnnamedTable (ID1,ID2)
WHERE (Status='Unprocessed')
私はあなたが制約でそれを行うことができるとは思わない. 挿入/更新操作にトリガーを実装する必要があります。SQL Server の問題は、トリガーが「AFTER」トリガーであることです。「BEFORE」トリガーのようなものはありません (ただし、「INSTEAD OF」トリガー タイプはあります。
したがって、トランザクションが制約に違反するかどうかを単にチェックするのではなく、トランザクションを実行し、それを精査し、制約が失敗した場合はロールバックするためにすべての作業を行う必要があります。
1 つは処理済みレコード用、もう 1 つは未処理レポート用の 2 つの基になるテーブルの結合であるビューを使用して、これを行うことができます。
ただし、ビュー自体を更新可能にすることはできず、レコードが処理済みから未処理に戻ることがあり、頻繁に変更されると、パフォーマンスが低下します。
また、並列処理シナリオについての考え方がより複雑になります。
上記の両方の制限は、削除と挿入によって一部の更新を置き換えているためです。
少なくとも SQL Server 2008 を使用している場合は、通常、フィルター選択されたインデックスの方が優れたソリューションです。
ProcessedId (Status ではなく) という列を作成し、ID1 と ID2 が処理されているかどうかに基づいて値を割り当てます。明確にするために、以下を参照してください
[ID1、ID2、プロセス ID]
SomeId1、SomeId2、-1
SomeOtherId1、SomeOtherId2、100304
そのため、未処理の ID のセットには常に ProcessId が -1 であり、ブロッキングと重複があり、PROCESSED の ID のセットには何らかの連番が割り当てられ、重複が許可されます。わかる?
したがって、上記の例を続けると、レコード セットが再び未処理で入ってきた場合、ProcessId が -1 になり、PK 違反が発生します。