簡略化したテーブルは次のようになります。
create table Test
(
ValidFrom date not null,
ValidTo date not null,
check (ValidTo > ValidFrom)
)
既存の日付範囲と重複する値の挿入を防ぐトリガーを作成したいと思います。私は次のようなトリガーを作成しました:
create trigger Trigger_Test
on Test
for insert
as
begin
if exists(
select *
from Test t
join inserted i
on ((i.ValidTo >= t.ValidFrom) and (i.ValidFrom <= t.ValidTo))
)
begin
raiserror (N'Overlapping range.', 16, 1);
rollback transaction;
return
end;
end
しかし、新しく挿入されたレコードは、テストとトリガー内に挿入された両方のテーブルの一部であるため、機能しません。したがって、挿入されたテーブルの新しいレコードは、常にテストテーブルでそれ自体に結合されます。トリガーは常に変換を元に戻します。
新しいレコードと既存のレコードを区別できません。したがって、同じ日付範囲を除外すると、テーブルにまったく同じ範囲を複数挿入できるようになります。
主な質問は
exists()
次のように、ステートメントから新しく挿入されたレコードを除外するために使用できるID列をテストテーブルに追加せずに、期待どおりに機能するトリガーを作成することは可能ですか?
create trigger Trigger_Test
on Test
for insert
as
begin
if exists(
select *
from Test t
join inserted i
on (
i.ID <> t.ID and /* exclude myself out */
i.ValidTo >= t.ValidFrom and i.ValidFrom <=t.ValidTo
)
)
begin
raiserror (N'Overlapping range.', 16, 1);
rollback transaction;
return
end;
end
重要:アイデンティティなしでは不可能なことが唯一の答えである場合は、その理由を合理的な説明とともに提示することを歓迎します。