重複を削除したら:
ALTER TABLE dbo.yourtablename
ADD CONSTRAINT uq_yourtablename UNIQUE(column1, column2);
または
CREATE UNIQUE INDEX uq_yourtablename
ON dbo.yourtablename(column1, column2);
もちろん、SQL Serverに行の挿入を試みて例外を返す前に、最初にこの違反をチェックする方がよい場合がよくあります(例外は高額です)。
-
さまざまなエラー処理手法によるパフォーマンスへの影響
-
TRY / CATCHに入る前に、潜在的な制約違反をチェックする
アプリケーションに変更を加えずに、例外がアプリケーションにバブリングするのを防ぎたい場合は、INSTEAD OF
を使用できます。 トリガー:
CREATE TRIGGER dbo.BlockDuplicatesYourTable
ON dbo.YourTable
INSTEAD OF INSERT
AS
BEGIN
SET NOCOUNT ON;
IF NOT EXISTS (SELECT 1 FROM inserted AS i
INNER JOIN dbo.YourTable AS t
ON i.column1 = t.column1
AND i.column2 = t.column2
)
BEGIN
INSERT dbo.YourTable(column1, column2, ...)
SELECT column1, column2, ... FROM inserted;
END
ELSE
BEGIN
PRINT 'Did nothing.';
END
END
GO
ただし、挿入を実行しなかったことをユーザーに通知しないと、なぜデータが存在せず、例外が報告されなかったのか疑問に思うでしょう。
編集 これは、質問と同じ名前を使用しても、あなたが求めていることを正確に実行し、それを証明する例です。上記のアイデアは、組み合わせではなく、どちらかの列のみを扱うと想定する前に、試してみてください...
USE tempdb;
GO
CREATE TABLE dbo.Person
(
ID INT IDENTITY(1,1) PRIMARY KEY,
Name NVARCHAR(32),
Active BIT,
PersonNumber INT
);
GO
ALTER TABLE dbo.Person
ADD CONSTRAINT uq_Person UNIQUE(PersonNumber, Active);
GO
-- succeeds:
INSERT dbo.Person(Name, Active, PersonNumber)
VALUES(N'foo', 1, 22);
GO
-- succeeds:
INSERT dbo.Person(Name, Active, PersonNumber)
VALUES(N'foo', 0, 22);
GO
-- fails:
INSERT dbo.Person(Name, Active, PersonNumber)
VALUES(N'foo', 1, 22);
GO
このすべての後のテーブルのデータ:
ID Name Active PersonNumber
---- ------ ------ ------------
1 foo 1 22
2 foo 0 22
最後の挿入のエラーメッセージ:
メッセージ2627、レベル14、状態1、行3UNIQUEKEY制約の違反'uq_Person'。オブジェクト'dbo.Person'に重複するキーを挿入できません。ステートメントは終了しました。
また、最近、2つの列にいずれかの順序で一意の制約を適用するための解決策についてブログを書きました。 :
- 順序が重要ではない場合に一意の制約を適用する