201

私はテーブルを持っていますが、どういうわけか、同じ人が私のPersonテーブルに 2 回入りました。現在、主キーは単なる自動採番ですが、強制的に一意にしたいフィールドが他に 2 つあります。

たとえば、フィールドは次のとおりです。

ID  
Name  
Active  
PersonNumber  

一意の PersonNumber と Active = 1 を持つ 1 つのレコードのみが必要です
(したがって、2 つのフィールドの組み合わせは一意である必要があります) 。

SQLサーバーの既存のテーブルで最善の方法は何ですか?他の誰かが既存の値と同じ値で挿入を行った場合、それは失敗するので、アプリケーションコードでこれについて心配する必要はありません.

4

4 に答える 4

295

重複を削除したら:

ALTER TABLE dbo.yourtablename
  ADD CONSTRAINT uq_yourtablename UNIQUE(column1, column2);

また

CREATE UNIQUE INDEX uq_yourtablename
  ON dbo.yourtablename(column1, column2);

もちろん、SQL Server に行の挿入を試行させて例外を返す前に、最初にこの違反をチェックする方がよい場合があります (例外はコストがかかります)。

アプリケーションに変更を加えることなく、例外がアプリケーションにバブリングするのを防ぎたい場合は、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、行 3 UNIQUE KEY 制約 'uq_Person' の違反。オブジェクト 'dbo.Person' に重複するキーを挿入できません。ステートメントは終了されました。

また、最近ブログで、一意の制約を 2 つの列にいずれかの順序で適用するソリューションについて説明しました。

于 2013-04-03T23:56:18.293 に答える
0

また、挿入クエリがたくさんあるが、毎回エラー メッセージを表示したくない場合は、次のように実行できます。

CREATE UNIQUE NONCLUSTERED INDEX SK01 ON dbo.Person(ID,Name,Active,PersonNumber) 
WITH(IGNORE_DUP_KEY = ON)

ここに画像の説明を入力

于 2020-02-01T06:04:07.837 に答える