web-dev-qa-db-ja.com

AdonisJS:belongsTo()リレーションシップの設計に何か問題がありますか?

AdonisJsフレームワークで、Profileモデルとの belongsTo() 関係を定義するUserモデルがあるとします。ドキュメントでは、これによりデータベースを次のように定義するようになります:

enter image description here

idテーブルの列usersは、profilesテーブルの主キーではなく、usersテーブルを参照する外部キーです。この「悪いDB設計」はいくつかの矛盾につながることができますか?

ビラル・ベゲラジ

2
Begueradj

リンクされたドキュメンテーションの唯一の問題はモデル画像のタイプミスだと思います:

usersid (FK)id (PK)を意味するものでした。
profilesuser_id (PK)user_id (FK)と言うことを意図していた。
リンクは逆方向でなければなりません(他のすべての図では、リンクはPK /参照テーブルから始まり、Fk /参照テーブルを指しています)。

belongsTo()の例の下の図は正しいようです(hasOne()でも使用する必要があります)。

デザインは、usersprofilesの間に1-1の関係、より正確には_1 - 0..1_の関係を示しています。

ユーザーは1つの(hasOne)プロファイルを持つことができます。プロファイルbelongs to(belongsTo)1人のユーザー。


図から欠落しているように見えるのは、関係が1対多ではなく1対1で真になるために、profiles (user_id)UNIQUE制約が必要であることです。おそらく、ORMがそのような制約を作成し、ダイアグラムを描画するときにそれを逃しました。

1
ypercubeᵀᴹ

まず、関係のカーディナリティを確立する必要があります。

多くのプロファイルを持つことができるユーザーがいて、特定のプロファイルが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 Entityjoiningテーブル-他の名前のリンクを参照)これは次のようになります。

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),
  -- ...
);

つまり、userprofileの間には相互関係があります。ただし、これによりmajorDEFERRED CONSTRAINTsをサポートしない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を使用する正当な理由があります。意味がない。

0
Vérace