web-dev-qa-db-ja.com

条件付き関係?エンティティのタイプのみにピボットテーブルを使用する1対多の関係

次の表があります。

users:
  - id
  - name
  - user_type_id (references id on user_types)

neighborhoods:
  - id
  - name

homes:
  - id
  - house_number
  - neighborhood_id (references id on neighborhoods)

user_types:
  - id
  - label

利用可能なuser_typesはresidentneighborhood_adminsuper_adminです。各タイプのユーザーは、システムのさまざまな部分にアクセスできます。居住者だけがhomesテーブルとの関係を持っている必要があります。

私は次のようなピボットテーブルを追加しようと考えていました:

residents:
  - user_id (references id on users)
  - home_id (references id on home)

しかし、このアプローチが正しいかどうかはわかりません。私は多対多の関係にのみピボットテーブルを使用しました。また、コードを使用して、家を割り当てる前にuser_typeを確認する必要がありますが、注意しなければ、家をsuper_adminに簡単に割り当てることもできます。

コードで実行する必要がないように、データベースにこの制限を適用するにはどうすればよいですか?

PDATE:追加するのを忘れたため、neighborhood_adminsを近隣に割り当てる必要があります。次の表を追加できます。

neighborhood_admins:
   - user_id (references id on users)
   - neighborhood_id (references id on neighborhoods)

しかし、これは問題を引き起こします。 usersテーブルはneighborhoodsテーブルと2つの異なる関係になりました。ユーザーがneighborhood_adminの場合、関係はピボットテーブルneighborhood_adminから取得されますが、ユーザーが居住者の場合、最初にhome関係を取得し、次に家の近隣を取得する必要があります。

neighborhood_id列をusersテーブルに追加するだけで済むと思いますが、これらの関係の三角形は好きではありません。また、super_adminsの場合、その列はnullになるため、外部キーにすることはできません。

2
Vic

ほとんどのRDBMSでは、このような場合に役立つ列条件を設定することができます。ユーザータイプが1、2、3であるとしましょう(それぞれ、res、admin、super)。次のようにusersを設定できます。

CREATE TABLE users (
  id serial NOT NULL PRIMARY KEY,
  name varchar(100) NOT NULL,
  user_type_id int NOT NULL REFERENCES user_types,
  home_id int NULL REFERENCES homes,
  -- a resident must have a home, a non-resident cannot have a home
  CHECK ((user_type_id = 1 AND home_id IS NOT NULL) OR
         (user_type_id <> 1 AND home_id IS NULL))
);