次の表があります。
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はresident、neighborhood_admin、super_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になるため、外部キーにすることはできません。
ほとんどの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))
);