sql >> データベース >  >> RDS >> Sqlserver

2つの列の組み合わせに一意性制約を追加します

    重複を削除したら:

    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つの列にいずれかの順序で一意の制約を適用するための解決策についてブログを書きました。 :

    • 順序が重要ではない場合に一意の制約を適用する


    1. Oracleでクエリ結果をコンマ区切りリストとして返す

    2. oracle.sql.ARRAYオブジェクトを作成するにはどうすればよいですか?

    3. SQLServerのGroupBy、Having、Where句の実行シーケンス?

    4. 日時からのトリミング時間–フォローアップ