169

データを保持するテーブルがあり、それらの行の 1 つが別のテーブルに存在する必要があります。したがって、参照整合性を維持するために外部キーが必要です。

CREATE TABLE table1
(
   ID INT NOT NULL IDENTITY(1,1) PRIMARY KEY,
   AnotherID INT NOT NULL,
   SomeData VARCHAR(100) NOT NULL
)

CREATE TABLE table2
(
   ID INT NOT NULL IDENTITY(1,1) PRIMARY KEY,
   AnotherID INT NOT NULL,
   MoreData VARCHAR(30) NOT NULL,

   CONSTRAINT fk_table2_table1 FOREIGN KEY (AnotherID) REFERENCES table1 (AnotherID)
)

ただし、ご覧のとおり、外部キーのテーブルである列は PK ではありません。この外部キーを作成する方法、またはこの参照整合性を維持するためのより良い方法はありますか?

4

5 に答える 5

231

非主キーへの外部キーを本当に作成したい場合は、一意の制約を持つ列である必要があります。

Books Onlineから:

FOREIGN KEY 制約は、別のテーブルの PRIMARY KEY 制約のみにリンクする必要はありません。別のテーブルの UNIQUE 制約の列を参照するように定義することもできます。

したがって、あなたの場合、AnotherID一意にすると許可されます。一意の制約を適用できない場合は運が悪いですが、考えてみればこれは本当に理にかなっています。

ただし、前述したように、候補キーとして完全に優れた主キーがある場合は、それを使用しないでください。

于 2013-08-26T00:36:24.843 に答える
25

他の人が指摘したように、理想的には、外部キーは主キー (通常は IDENTITY 列) への参照として作成されます。ただし、私たちは理想的な世界に住んでいるわけではなく、スキーマの "小さな" 変更でさえ、アプリケーション ロジックに大きな影響を与えることがあります。

SSN 列 (およびダム主キー) を持つ Customer テーブルと、SSN 列も含む Claim テーブル (Customer データからビジネス ロジックによって入力されますが、FK は存在しません) のケースを考えてみましょう。設計には欠陥がありますが、数年間使用されており、3 つの異なるアプリケーションがスキーマに基づいて構築されています。Claim.SSN を取り除き、実際の PK-FK 関係を組み込むことが理想的であることは明らかですが、大幅なオーバーホールにもなります。一方、Customer.SSN に UNIQUE 制約を設定し、Claim.SSN に FK を追加すると、アプリケーションにほとんどまたはまったく影響を与えずに、参照整合性を提供できます。

誤解しないでほしいのですが、私は正常化に大賛成ですが、現実主義が理想主義に勝ることもあります。バンドエイドで平凡なデザインを助けることができれば、手術は避けられるかもしれません.

于 2014-05-15T20:47:54.083 に答える
-1

はい、通常は少なくともインデックスを作成します。

create table student(
    id int,
    name varchar(30),
    index inName(id)
);

CREATE TABLE grade(
    id int,
    subject varchar(30),
    mark double,
    foreign key(id) references student(id)
);
于 2021-08-30T18:44:34.033 に答える