2016-07-04 6 views
1

私は何かの一意性を明示的に定義することに関して質問があります。これは複合外部キーの作成に関係します。私は可能な限り私の質問をしようとするために、以下の例を作成しました(テストの容易さのためにいくつかのデータ挿入を含んでいます)。複合外部キーの場合、主キーとの列の組み合わせに必要な参照先テーブルの複合UNIQUE制約は/ whyですか?

[Table1]の各エントリには、一意の[Name]が必要です。

CREATE TABLE [Table1] 
(
    [ID] INT IDENTITY   NOT NULL PRIMARY KEY, 
    [Name] NVARCHAR(255) UNIQUE NOT NULL CHECK(LTRIM(RTRIM([Name])) <> '') 
); 

INSERT INTO [Table1]([Name]) 
VALUES 
('Name 1'), 
('Name 2'), 
('Name 3'), 
('Name 4'), 
('Name 5'), 
('Name 6'), 
('Name 7') 

[Table2]の各[Value]は、各[Table1ID]のために一意である必要があります。

CREATE TABLE [Table2] 
(
    [ID]  INT IDENTITY NOT NULL PRIMARY KEY, 
    [Table1ID] INT    NOT NULL FOREIGN KEY REFERENCES [Table1]([ID]), 
    [Value]  NVARCHAR(255) NOT NULL CHECK(LTRIM(RTRIM([Value])) <> ''), 

    --UNIQUE([ID], [Table1ID]), 
    UNIQUE([Table1ID], [Value]) 
); 

INSERT INTO [Table2]([Table1ID], [Value]) 
VALUES 
(1, 'Entry 1'), 
(1, 'Entry 2'), 
(1, 'Entry 3'), 
(1, 'Entry 4'), 
(3, 'Entry 5'), 
(3, 'Entry 6'), 
(3, 'Entry 7') 

[Table3][Table1ID][Table2ID]の各組み合わせは[Table2]に一致する組み合わせを持っている必要があります(私は、複合FOREIGN KEYが所定の位置にある場合[Table1ID][Table2ID]ための2つのFOREIGN KEY sが余分になることを想定しています?)。 [Table3]における複合FOREIGN KEY制約が問題であること

CREATE TABLE [Table3] 
(
    [ID]  INT IDENTITY NOT NULL, 
    [Table1ID] INT    NOT NULL FOREIGN KEY REFERENCES [Table1]([ID]), 
    [Table2ID] INT    NOT NULL FOREIGN KEY REFERENCES [Table2]([ID]), 

    FOREIGN KEY ([Table2ID], [Table1ID]) REFERENCES [Table2](ID, [Table1ID]) 
); 

INSERT INTO [Table3]([Table2ID], [Table1ID]) 
VALUES 
(5, 3) 

。コメントアウトされたUNIQUEの制約が[Table2]である場合は、コメントを外すと[Table3]を正常に作成できます。そうでない場合、[Table3]の作成では、「外部キーの参照列リストと一致する参照先テーブルにプライマリキーまたは候補キーがありません」というメッセージが表示されません。

私はしかし[Table2]ため[ID]列がPRIMARY KEYであり、常にユニークであるように、なぜ[Table2]にユニークされていない[Table1ID]列が[Table2][ID][Table1ID]の任意の組み合わせを防止するであろう、キーに関して持つ一意の必要性を理解ユニークであることから?

基本的には、UNIQUE([ID], [Table1ID])部分は私にはかなり余計ようだ、まだ[Table2][Table1ID]の一意性を明示的にSQL Serverが[Table3]複合外部キーの作成を可能にするために定義されなければならないようです。

実際はそうですか?この制約は、余分に見えるかもしれませんが、上記を可能にするために必要ですか?または私は何かを逃していますか?

+0

はい、一意性が宣言されていなければなりません。私はあなたが求めていることをする必要があるデータ設計に疑問を呈します。 – Paparazzi

+0

もう一度、私は物事を実証するための例として上記をまとめました。データ設計コメントを拡張することはできますか? – Interminable

+0

私はこれをまっすぐにしましょう。 Table2はすでにTable1との関係を持っています。表3では、1と2の間の関係を直接作成したいと同時に、既存の関係2に1を尊重したいと考えています。そのような関係の合理的なビジネスニーズを広げることができますか? – Paparazzi

答えて

1

実際にリレーショナルデータベースの理論的側面と関連があります。

親テーブル内での外部キーの参照は、任意の列のセットではありませんが、ユニークである可能性があります。プライマリまたは代替のいずれかのキーを参照します。そして、この鍵は、そのように明確に宣言されなければなりません。

+0

また、参照テーブルのUNIQUE制約は、複合FOREIGN KEY制約のために参照可能なキーとしてカウントされますか? – Interminable

+0

@Interminable、yes - 学問的に言えば、代替キーです。驚くかもしれませんが、SQL Serverでもユニークなインデックスでも参照されたキーとして扱うことができます(フィルタされたインデックスについてはわかりません)。 –

+0

@philipxy、私はデータベースがここで "より良い安全な"戦略を採用していると思います。キーを参照すると、それ以上削除することはできません。ただし、列のサブセットのみがキーとして宣言されている場合、データベースエンジンは、親テーブルから特定のキーを削除するかどうかを判断しようとすると、あまりにも多くの作業を行う必要があります。さらに、このようなルールの屈曲によって生じる曖昧さのレベルは、悲惨なものになります。 –

0

ユニークな列セットのスーパーセットは一意です。 DBMSはこれを理解するようにプログラムすることができます。しかし、SQLでは、参照されたテーブルでユニークな組み合わせを宣言する必要があります。

PSリレーショナルモデルでは、外部キーは候補キーを参照する必要があります。両方とも宣言する必要があります。しかし、SQLでは、UNIQUEはスーパーキーを宣言し、FOREIGN KEYは外部スーパーキーを宣言します。 (スーパーキーに小さいスーパーキーが含まれていない場合は候補キーです)。外国スーパーキー宣言のターゲットには、明示的に一致する一意の宣言があると人間工学的な冗長性を優先することができます。しかし、そのための理論的または実装上の正当性はない。

関連する問題