AdonisJsフレームワークで、Profile
モデルとの belongsTo()
関係を定義するUser
モデルがあるとします。ドキュメントでは、これによりデータベースを次のように定義するようになります:
id
テーブルの列users
は、profiles
テーブルの主キーではなく、users
テーブルを参照する外部キーです。この「悪いDB設計」はいくつかの矛盾につながることができますか?
ビラル・ベゲラジ
リンクされたドキュメンテーションの唯一の問題はモデル画像のタイプミスだと思います:
users
列id (FK)
はid (PK)
を意味するものでした。profiles
列user_id (PK)
はuser_id (FK)
と言うことを意図していた。
リンクは逆方向でなければなりません(他のすべての図では、リンクはPK /参照テーブルから始まり、Fk /参照テーブルを指しています)。
belongsTo()
の例の下の図は正しいようです(hasOne()
でも使用する必要があります)。
デザインは、users
とprofiles
の間に1-1の関係、より正確には_1 - 0..1
_の関係を示しています。
ユーザーは1つの(hasOne)プロファイルを持つことができます。プロファイルbelongs to(belongsTo)1人のユーザー。
図から欠落しているように見えるのは、関係が1対多ではなく1対1で真になるために、profiles (user_id)
にUNIQUE
制約が必要であることです。おそらく、ORMがそのような制約を作成し、ダイアグラムを描画するときにそれを逃しました。
まず、関係のカーディナリティを確立する必要があります。
多くのプロファイルを持つことができるユーザーがいて、特定のプロファイルが1人のユーザーにしか所属できない場合は、
CREATE TABLE user -- all fields are INTs unless otherwise indicated
(
user_id CONSTRAINT user_pk PRIMARY KEY, -- <<=== normal practice is to have a surrogate key - AUTO_GEN or SEQUENCES or similar
user_name VARCHAR,
...,
..., -- other user stuff...
..
);
CREATE TABLE profile
(
profile_id CONSTRAINT profile_pk PRIMARY KEY,
user_id,
CONSTRAINT profile_user_fk FOREIGN KEY (user_id) REFERENCES user (user_id),
-- exact syntax may vary...
... other stuff
);
それぞれが多くのプロファイルを持つ可能性のある多くのユーザーがいる場合(サイトごとに異なるプロファイルを持つことができるStackExchange/StackOverflowのユーザーをここで考えてください)、 Associative Entity ( joining
テーブル-他の名前のリンクを参照)これは次のようになります。
CREATE TABLE user
(
user_id,
... other stuff
);
CREATE TABLE profile
(
profile_id,
... other stuff
);
CREATE TABLE user_profile
(
user_id,
profile_id
CONSTRAINT up_user_fk FOREIGN KEY (user_id) REFERENCES user (user_id),
CONSTRAINT up_profile_fk FOREIGN KEY (profile_id) REFERENCES profile (profile_id)
); -- <<== again, syntax may vary
特定のユーザーが1つのプロファイルと1つだけプロファイルを持つことができるあなた自身の特定のケースでは、次のようになります。
CREATE TABLE user
(
user_id PK, -- plus other fields
profile_id CONSTRAINT user_profile_fk FOREIGN KEY REFERENCES profile (profile_id),
-- ...
);
特定のユーザーが複数のプロファイルを持っている可能性が高いと思われるので、ユーザーテーブルからFKを除外しますか?これにより、この可能性を検討している場合に、後で複数のプロファイルを簡単に追加できます。
CREATE TABLE profile
(
profile_id PK, -- plus other fields
user_id CONSTRAINT profile_user_fk FOREIGN KEY REFERENCES user (user_id),
-- ...
);
つまり、user
とprofile
の間には相互関係があります。ただし、これによりmajorDEFERRED CONSTRAINT
sをサポートしないMySQLの問題が発生します-こちらを参照してください(2019年2月現在、MySQLの最新バージョン)。
一般的なMySQLと同様に、多くの行を挿入、削除、または更新するSQLステートメントでは、InnoDBは行ごとにUNIQUEおよびFOREIGN KEY制約をチェックします。外部キーチェックを実行すると、InnoDBは、参照する必要がある子レコードまたは親レコードに共有行レベルのロックを設定します。 InnoDBは外部キー制約をすぐにチェックします。チェックはトランザクションのコミットまで延期されません。 SQL標準によると、デフォルトの動作は据え置きチェックです。つまり、SQLステートメント全体が処理された後でのみ制約がチェックされます。 InnoDBが遅延制約チェックを実装するまで、外部キーを使用してそれ自体を参照するレコードを削除するなど、いくつかのことは不可能です。
エンティティ間に1 <-> 1の厳密で変更されない関係がある場合、mayに「なぜ2つのテーブルがあるのですか?」と自問してください。それはそのように「整然としている」かもしれません、そして、または他の要素が作用するかもしれません-しかし、それは考慮する価値がありますか?あなた(もう一度)may後で再設計を検討しているので、ここでテーブルを分割することをお勧めします。
質問に関しては、絶対にnoprofile
テーブルのuser_id
としてPRIMARY KEY
を使用する正当な理由があります。意味がない。