質問

列を明確な値にしたいときは、制約を使用できます

create table t1(
id int primary key,
code varchar(10) unique NULL
);
go

または、一意のインデックスを使用できます

create table t2(
id int primary key,
code varchar(10) NULL
);
go

create unique index I_t2 on t2(code);

一意の制約のある列は、一意のインデックスの良い候補のようです。

一意の制約を使用し、代わりに一意のインデックスを使用しないという既知の理由はありますか?

役に立ちましたか?

解決

フードの下では、一意の制約が一意のインデックスと同じ方法で実装されます - 制約を強制するための要件を効率的に満たすためにインデックスが必要です。インデックスが一意の制約の結果として作成されたとしても、クエリプランナーは、特定のクエリにアプローチする最良の方法として見られる場合、他のインデックスと同様に使用できます。

したがって、両方の機能をサポートするデータベースの場合、使用する選択肢の選択は、しばしば好ましいスタイルと一貫性に依存します。

インデックスをインデックスとして使用することを計画している場合(つまり、コードがそのフィールドでの検索/並べ替え/フィルタリングに依存する場合があります)。クリア - この方法で、アプリケーション(または他のコーダー)の後の改訂で一意性要件が変更された場合、ユニークなインデックスが一意のインデックスの場所に配置されることを確認するために知っています(一意の制約を削除するだけで削除されますインデックスは完全に)。また、特定のインデックスは、インデックスヒント(つまり(IX_INDEX_NAME)を含む)で名前を付けることができます。

同様に、フィールドを検索する必要があるか、ソートに使用する必要があるのではなく、ユニーク性をビジネスルールとして実施する必要がある場合、制約を使用して、他の誰かがテーブルの定義を見たときに意図した使用をより明白にします。

同じフィールドで一意の制約と一意のインデックスの両方を使用すると、データベースは複製を見るほど明るくないため、余分なスペースを消費して列の挿入/更新を遅くする2つのインデックスが表示されることに注意してください。

他のヒント

他の回答のポイントに加えて、2つの間にいくつかの重要な違いがあります。

注:エラーメッセージは、SQL Server 2012からのものです。

エラー

一意の制約の違反は、エラー2627を返します。

Msg 2627, Level 14, State 1, Line 1
Violation of UNIQUE KEY constraint 'P1U_pk'. Cannot insert duplicate key in object 'dbo.P1U'. The duplicate key value is (1).
The statement has been terminated.

一意のインデックスの違反は、エラー2601を返します。

Msg 2601, Level 14, State 1, Line 1
Cannot insert duplicate key row in object 'dbo.P1' with unique index 'P1_u'. The duplicate key value is (1).
The statement has been terminated.

無効化

一意の制約を無効にすることはできません。

Msg 11415, Level 16, State 1, Line 1
Object 'P1U_pk' cannot be disabled or enabled. This action applies only to foreign key and check constraints.
Msg 4916, Level 16, State 0, Line 1
Could not enable or disable the constraint. See previous errors.

ただし、一意のインデックスと同様に、主要なキーの制約または一意の制約の背後にある一意のインデックスを無効にすることができます。 ハットチップBrain2000。

ALTER INDEX P1_u ON dbo.P1 DISABLE ;

クラスター化されたインデックスを無効にすると、データがアクセスできないという通常の警告に注意してください。

オプション

一意の制約は、次のようなインデックス作成オプションをサポートします FILLFACTORIGNORE_DUP_KEY, 、これはSQL Serverのすべてのバージョンに当てはまりません。

含まれている列

クラスタリングされていないインデックスには、インデックスされていない列を含めることができます(カバーインデックスと呼ばれる、これは主要なパフォーマンス向上です)。プライマリキーと一意の制約の背後にあるインデックスには、列を含めることはできません。 hat-tip @ypercube。

フィルタリング

一意の制約をフィルタリングすることはできません。

一意のインデックスをフィルタリングできます。

CREATE UNIQUE NONCLUSTERED INDEX Students6_DrivesLicence_u 
ON dbo.Students6( DriversLicenceNo ) WHERE DriversLicenceNo is not null ;

外部キーの制約

外部キーの制約は、フィルタリングされた一意のインデックスを参照することはできませんが、フィルタリングされていない一意のインデックスを参照できます(これはSQL Server 2005に追加されたと思います)。

ネーミング

制約を作成する場合、制約名を指定することはオプションです(5種類の制約すべてに対して)。名前を指定しない場合、MSSQLはお客様のために生成されます。

CREATE TABLE dbo.T1 (
    TID int not null PRIMARY KEY
) ;
GO
CREATE TABLE dbo.T2 (
    TID int not null CONSTRAINT T2_pk PRIMARY KEY
) ;

インデックスを作成するときは、名前を指定する必要があります。

hat-tip @i-one。

リンク

http://technet.microsoft.com/en-us/library/aa224827(v=sql.80).aspx

http://technet.microsoft.com/en-us/library/ms177456.aspx

権威ある出典としてMSDNを引用するには:

一意の制約を作成することと、制約に依存しない一意のインデックスを作成することとの間には大きな違いはありません。. 。データ検証は同じ方法で発生し、クエリオプティマイザーは、制約によって作成されたまたは手動で作成された一意のインデックスを区別しません。ただし、列に一意の制約を作成すると、インデックスの目的が明確になります... 詳細については、こちらをご覧ください

と...

データベースエンジンは、一意の制約の一意性要件を実施するための一意のインデックスを自動的に作成します。 したがって、重複した行を挿入しようとすると、データベースエンジンは、一意の制約が違反されており、テーブルに行を追加しないというエラーメッセージを返します。クラスター化されたインデックスが明示的に指定されていない限り、一意の非クラスター化されたインデックスがデフォルトで作成され、一意の制約を強制します... 詳細については、こちらをご覧ください

その他: https://technet.microsoft.com/en-us/library/aa224827%28v = sql.80%29.aspx

一意の制約と一意のインデックスの主な違いの1つは、別のテーブルの外部キーの制約が一意の制約を構成する列を参照できることです。これは、一意のインデックスには当てはまりません。さらに、一意の制約はANSI標準の一部として定義されますが、インデックスはそうではありません。最後に、インデックスは物理的な側面である間、論理データベース設計の領域(異なるDBエンジンによって異なる方法で実装される場合がある)の領域に住んでいると見なされる独自の制約があります。したがって、一意の制約はより宣言的です。私はほとんどすべての場合に独自の制約を好むでしょう。

Oracleでは、大きな違いは、一意の制約では機能しない機能インデックスを作成できることです。

例えば

create unique index ux_test on my_table (case when amount != 0 then fk_xyz end);

それで fk_xyz レコードにとってのみユニークです amount != 0.

一意の制約は、一意のインデックスよりも推奨されます。制約が一意でない場合は、通常のインデックスまたは非一意のインデックスを使用する必要があります。制約は、別のタイプのインデックスでもあります。インデックスは、より速いアクセスに使用されます。

一意のインデックスは、条項を持つことができます。たとえば、日付列に基づいて毎年インデックスを作成できます

WHERE Sale_Date BETWEEN '2012-01-01' AND '2012-12-31'
ライセンス: CC-BY-SA帰属
所属していません dba.stackexchange
scroll top