Composite Foreign Key from multiple related tables

徘徊边缘 提交于 2019-12-25 08:49:46

问题


Just beginning to learn about SQL and had a question I couldn't figure out.

I have a setup based on the following tables and their primary keys, the columns with the same name between tables are constrained by foreign keys:

Company:

  • CompanyId

Division:

  • CompanyId
  • DivisionId

Resource:

  • CompanyId
  • ResourceId

DivisionResource :

  • CompanyId
  • DivisionId
  • ResourceId
  • DivisionResource is used to create a many to many relation between division and resource and constrain them so that divisions can only be linked to resources of the same company.
  • Without the DivisionResource, Division and Resource wouldn't need the CompanyId as a primary key to contain unique records.

So my question is this: Is there a way to create a similar constraint as DivisionResource creates without forcing Division and Resource to have an extra column in its primary key?


回答1:


ResourceCompany and DivisionCompany in the schema below are connecting tables. They will have CompanyId in their primary key but Resource and Division will have primary keys with one column. This is what you looked for.

Resource -> ResourceCompany

DivisionResource -> ResourceCompany

Division -> 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)
    );



回答2:


Create INSTEAD OF trigger on insert and update of DivisionResource

The trigger will check if Divistion and Resource have the same company. If they don't, it will fail the modification

Alternatively, it would be even better to have a stored procedure modifying DivisionResource. Then the trigger needs to call it.




回答3:


I'm assuming that you're trying to create the following schema:

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))

Which throws:

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.

Changing either divisionId or resourceId to ON DELETE NO ACTION ON UPDATE NO ACTION will essentially break the referential integrity. What I suggested in my comment was to make a surrogate key. However, it would be better if you created a separate table for resource. This will maintain the referential integrity and also normalize the schema:

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))


来源:https://stackoverflow.com/questions/14391483/composite-foreign-key-from-multiple-related-tables

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!