来自多个相关表的复合外键

时间:2013-01-18 02:21:28

标签: sql foreign-keys composite-key

刚刚开始学习SQL并且有一个我无法弄清楚的问题。

我有一个基于以下表及其主键的设置,表之间具有相同名称的列受外键约束:

  

公司:

     
      
  • CompanyId
  •   
     

司:

     
      
  • CompanyId
  •   
  • DivisionId
  •   
     

资源:

     
      
  • CompanyId
  •   
  • RESOURCEID
  •   
     

DivisionResource:

     
      
  • CompanyId
  •   
  • DivisionId
  •   
  • RESOURCEID
  •   
  • DivisionResource用于在部门和资源之间创建多对多的关系并对其进行约束,以便划分只能链接到同一公司的资源。
  • 如果没有DivisionResource,Division和Resource就不需要将CompanyId作为包含唯一记录的主键。

所以我的问题是:有没有办法在DivisionResource创建时创建一个类似的约束而不强制Division和Resource在其主键中有一个额外的列?

3 个答案:

答案 0 :(得分:1)

下面架构中的ResourceCompany和DivisionCompany是连接表。他们的主键中将包含CompanyId,但Resource和Division将具有一列的主键。这就是你要找的东西。

  

资源 - > ResourceCompany

     

DivisionResource - > ResourceCompany

     

分部 - > DivisionCompany

     

DivisionResource - > DivisionCompany

create table Company (CompanyId int primary key);

create table DivisionCompany (
    CompanyId int foreign key references Company(CompanyId), 
    DivisionId int, 
    constraint pk_div_company primary key (DivisionId, CompanyId)
    );

create table Division (
    DivisionId int primary key,
    CompanyId int,
    constraint fk_div_company foreign key (DivisionId, CompanyId) references DivisionCompany(DivisionId, CompanyId));

create table ResourceCompany (
    CompanyId int foreign key references Company(CompanyId), 
    ResourceId int, 
    constraint pk_res primary key (ResourceId, CompanyId));

create table Resource(
    ResourceId int primary key,
    CompanyId int, 
    constraint fk_res_company foreign key (ResourceId, CompanyId) references ResourceCompany(ResourceId, CompanyId)
    );

create table DivisionResource(
    CompanyId int,
    DivisionId int, 
    ResourceId int,
    constraint pk_DivRes primary key (DivisionId, ResourceId),
    constraint fk_DivCompany foreign key (DivisionId, CompanyId) references DivisionCompany(DivisionId, CompanyId),
    constraint fk_ResCompany foreign key (ResourceId, CompanyId) references ResourceCompany(ResourceId, CompanyId)
    );

答案 1 :(得分:0)

在插入和更新DivisionResource

时创建INSTEAD OF触发器

触发器将检查Divistion和Resource是否拥有相同的公司。如果他们不这样做,它将无法修改

或者,使用修改DivisionResource的存储过程会更好。然后触发器需要调用它。

答案 2 :(得分:0)

我假设您正在尝试创建以下架构:

CREATE TABLE company (
  companyId int PRIMARY KEY)

CREATE TABLE division (
  divisionId int PRIMARY KEY,
  companyId int
    REFERENCES company (companyId) ON DELETE CASCADE ON UPDATE CASCADE)

CREATE TABLE resource (
  resourceId int PRIMARY KEY,
  companyId int
    REFERENCES company (companyId) ON DELETE CASCADE ON UPDATE CASCADE)

CREATE TABLE divisionResource (
  divisionId int
    REFERENCES division (divisionId) ON DELETE CASCADE ON UPDATE CASCADE,
  resourceId int
    REFERENCES resource (resourceId) ON DELETE CASCADE ON UPDATE CASCADE,
  PRIMARY KEY (divisionId, resourceId))

引发:

Introducing FOREIGN KEY constraint on table 'divisionResource' may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints.

divisionIdresourceId更改为ON DELETE NO ACTION ON UPDATE NO ACTION基本上会破坏参照完整性。我在评论中建议的是制作代理密钥。但是,如果为resource创建单独的表格会更好。这将保持参照完整性并规范化架构:

CREATE TABLE company (
  companyId int PRIMARY KEY)

CREATE TABLE division (
  divisionId int PRIMARY KEY,
  companyId int
    REFERENCES company (companyId) ON DELETE CASCADE ON UPDATE CASCADE)

CREATE TABLE resource (
  resourceId int PRIMARY KEY)

CREATE TABLE companyResource (
  resourceId int
    REFERENCES resource (resourceId) ON DELETE CASCADE ON UPDATE CASCADE,
  companyId int
    REFERENCES company (companyId) ON DELETE CASCADE ON UPDATE CASCADE)

CREATE TABLE divisionResource (
  divisionId int
    REFERENCES division (divisionId) ON DELETE CASCADE ON UPDATE CASCADE,
  resourceId int
    REFERENCES resource (resourceId) ON DELETE CASCADE ON UPDATE CASCADE,
  PRIMARY KEY (divisionId, resourceId))