web-dev-qa-db-ja.com

外部キーは同じテーブルの主キーを参照できますか?

外部キーにはuniquenessプロパティがないため、答えは偽だと思います。

しかし、一部の人々は、テーブルに自己参加する場合があり得ると言いました。 SQLが初めてです。その本当の場合、その方法と理由を説明してください。

Employee table
| e_id | e_name  | e_sala  |  d_id  |
|----  |-------  |-----    |--------|
|  1   |   Tom   |  50K    |    A   |
|  2   | Billy   |  15K    |    A   |
|  3   | Bucky   |  15K    |    B   |


department table
| d_id | d_name  |
|----  |-------  |
|  A   |   XXX   | 
|  B   |   YYY   | 

現在、d_idは外部キーであるため、どのように主キーになりますか。そして、joinについて何か説明してください。その用途は何ですか?

54
AmanS

質問は少しわかりにくいと思います。

「外部キーが同じテーブルの主キーを「参照」できるか」という意味であれば、答えは「はい」です。たとえば、従業員テーブルでは、従業員の行にマネージャーの従業員番号を格納する列があり、マネージャーも従業員であるため、テーブルには他の従業員の行のような行があります。

「列(または列のセット)を主キーと同じテーブルの外部キーにすることはできますか?」という意味であれば、私の意見では、答えはノーです。意味がないようです。ただし、次の定義はSQL Serverで成功します!

create table t1(c1 int not null primary key foreign key references t1(c1))

しかし、誰かが実用的な例を考え出さない限り、そのような制約を持つことは無意味だと思います。

AmanS、あなたの例では、どのような状況でもd_idがEmployeeテーブルの主キーになることはありません。テーブルに含めることができる主キーは1つだけです。これがあなたの疑念をクリアすることを願っています。 d_idは部門テーブルでのみ主キーになります。

70
mvsagar

もちろん? Personidname、およびparent_idを含むageテーブルがあるとします。ここで、parent_idは同じテーブルの外部キーです。 PersonテーブルをParentおよびChildテーブルに正規化する必要はありません。これはやり過ぎです。

Person
| id |  name | age | parent_id |
|----|-------|-----|-----------|
|  1 |   Tom |  50 |      null |
|  2 | Billy |  15 |         1 |

このようなもの。

ただし、一貫性を維持するには、parent_idに少なくとも1つのnull値が必要です。 1つの「アルファ雄」列。

編集:コメントが示すように、サムはこれをしない正当な理由を見つけました。 MySQLでは、CASCADE ON UPDATEを指定しても、主キーを編集しようとすると、編集が適切に伝播されないようです。主キーは(通常)本番環境での編集の制限ではありませんが、それでも無視されない制限です。したがって、私は私の答えを次のように変更します:-あなたはおそらくあなたが生産システムをかなり厳密に制御していない限り(おそらく誰もこの実装を避けるべきではありません PKを編集するコントロール)。 MySQL以外ではテストしていません。

16
ryvantage

例:カテゴリのnサブカテゴリレベル。テーブルの主キーidの下は外部キーsub_category_idによって参照されます

enter image description here

6
Nimya V

これは良い説明の例かもしれません

CREATE TABLE employees (
id INTEGER NOT NULL PRIMARY KEY,
managerId INTEGER REFERENCES employees(id), 
name VARCHAR(30) NOT NULL
);

INSERT INTO employees(id, managerId, name) VALUES(1, NULL, 'John');
INSERT INTO employees(id, managerId, name) VALUES(2, 1, 'Mike');

-説明:-この例では。 -ジョンはマイクのマネージャーです。マイクは誰も管理しません。 -マイクは誰も管理していない唯一の従業員です。

外部キーと同じテーブル内の他の行のIDを使用する良い例は、ネストされたリストです。

子を持つ行(つまり、親のIDを参照する行)を削除すると、子を持つ(つまり、子のIDを参照する)行のカスケードが削除されます。

これにより、多くの苦痛(および孤立したID、つまり、存在しないIDを参照する行)を処理するための多くのコードが節約されます。

1
bbe