连接表上的SQL约束

时间:2014-12-11 01:42:54

标签: sql postgresql

我在PostgreSQL数据库中有四个表:

  • 公司
    • 用户(使用外键列company_id)
    • 位置(使用外键列company_id)
    • UserLocations(关联表,外键列user_id和location_id)

基本上:

  • 公司有很多用户和位置
  • 用户属于公司并且拥有多个位置
  • 某个地点属于公司且拥有众多用户

我想知道数据库是否有办法约束UserLocations关联表中的条目,以使引用的用户和位置必须具有相同的company_id值。我不希望公司A的用户拥有公司B的位置。

我可以在我的应用程序层(rails)检查这个,但如果选项存在,我会有兴趣将其作为硬数据库级别约束。

2 个答案:

答案 0 :(得分:2)

您可以通过外键引用和冗余来实现此目的。

因此,UserLocations表格会有UserIdLocationIdCompanyId。然后它将具有以下外键关系:

foreign key (UserId, CompanyId) references Users(UserId, CompanyId)
foreign key (LocationId, CompanyId) references Locations(LocationId, CompanyId)

当然,您必须将Users(UserId, CompanyId)Locations(LocationId, CompanyId)声明为引用的唯一键。这有点多余,但它确保与公司匹配而不创建触发器。

答案 1 :(得分:1)

重叠外键约束是你的朋友。

create table company (
  company_id integer primary key
);

-- Reserved words include "user". Better to use identifiers that
-- are not reserved words.
create table "user" (
  user_id integer primary key,
  company_id integer not null references company (company_id),
  -- Unique constraint lets this be the target of a foreign key reference.
  unique (user_id, company_id)
);

create table location (
  location_id integer primary key,
  company_id integer not null references company (company_id),
  unique (location_id, company_id)
);

create table user_location (
  user_id integer not null,
  location_id integer not null,
  company_id integer not null,
  -- Not sure what your primary key is here. 

  -- These foreign keys overlap on the column "company_id", so there
  -- can be only one value for it.
  foreign key (user_id, company_id) references "user" (user_id, company_id),
  foreign key (location_id, company_id) references location (location_id, company_id)
);