MS2000で作業しているので、ジョブ(JPSID)をそれらを所有する従業員(EmpID)にマップするJobOwnersというテーブルがあります。また、そのジョブの所有を開始した日付(DateStarted)、そのジョブの所有を停止した日付(DateEnded)、および所有権がアクティブかどうか(IsActive)も含まれます。このように見えます。
CREATE TABLE JobOwners
(
LogID int NOT NULL IDENTITY(1,1) PRIMARY KEY,
JPSID int NOT NULL FOREIGN KEY REFERENCES JobsPerShift(JPSID),
EmpID int NOT NULL FOREIGN KEY REFERENCES Employees(EmpID),
DateStarted datetime,
DateEnded datetime,
IsActive tinyint NOT NULL
)
非アクティブな複製は問題ありませんが、アクティブなJPSIDの複製があってはなりません。いくつかの調査で、CHECK制約の関数を使用してこれを達成できることがわかりました。
CREATE FUNCTION CheckActiveCount(@JPSID INT)
RETURNS INT AS
BEGIN
DECLARE @result INT
SELECT @result = COUNT(*) FROM JobOwners WHERE JPSID = @JPSID AND IsActive = 1
RETURN @result
END
GO
ALTER TABLE JobOwners
ADD CONSTRAINT CK_JobOwners_IsActive
CHECK ((IsActive = 1 AND dbo.CheckActiveCount(JPSID) <= 1) OR (IsActive = 0))
これで十分に機能します。他にアクティブなJPSID2がないため、IsActive1でJPSID2を挿入できます。IsActiveが0の場合はチェックが適用されないため、IsActive0でJPSID2を挿入できます。ただし、制約と競合するため、JPSID2をIsActive1とともに再度挿入します。下記参照。
INSERT INTO JobOwners
VALUES(2,2,NULL,NULL,1)
(1 row(s) affected)
INSERT INTO JobOwners
VALUES(2,2,NULL,NULL,0)
(1 row(s) affected)
INSERT INTO JobOwners
VALUES(2,3,NULL,NULL,1)
INSERT statement conflicted with COLUMN FOREIGN KEY constraint...
非アクティブなレコードの1つをアクティブに更新しようとすると、問題が発生します。どういうわけか、それは私を可能にします。
UPDATE JobOwners SET IsActive = 1
WHERE LogID = 3
(1 row(s) affected)
同じステートメントを再度実行すると、制約と競合しますが、初回は競合しません。このアプリのフロントエンドは、非アクティブなレコードをアクティブに変更することはなく、新しいレコードを挿入するだけですが、それでもテーブルで許可したいものではありません。
アクティブなジョブ所有者を分離し、ジョブ所有者の履歴用に別のテーブルを用意するのが最善かどうか疑問に思っていますが、ここでのベストプラクティスについてはわかりません。どんな助けでも大歓迎です。
ありがとう、
ベン