sql—为多个表之一设计外键

rqmkfv5c  于 2021-07-26  发布在  Java
关注(0)|答案(3)|浏览(326)

我有三张table: Customers , Providers 以及 Locations . 我需要创建第四个表,名为 Contacts .
我想要任何数量的 Contacts 与中的任何行关联 Customers , Providers 以及 Locations 所以我就这样结束了。

CREATE TABLE [dbo].[Contacts] (
    [Id]         INT            IDENTITY (1, 1) NOT NULL,
    [CustomerId] INT            NULL,
    [ProviderId] INT            NULL,
    [LocationId] INT            NULL,
    [Name]       NVARCHAR (80)  NULL,
    [Email]      NVARCHAR (80)  NULL,
    [Phone]      NVARCHAR (80)  NULL,
    [Title]      NVARCHAR (80)  NULL,
    [Address]    NVARCHAR (120) NULL,
);

我觉得这个不太优雅。除了有未使用的列之外,我可能还应该添加一个约束来确保 CustomerId , ProviderId 以及 LocationId 不是 NULL .
另一种方法是创建多对多联接表。这将不需要任何未使用的列。但这似乎仍然是一种浪费,因为任何联系人都不会涉及多家公司。
有人知道有什么更巧妙的解决方案吗?

fcy6dtqo

fcy6dtqo1#

另一种方法是恢复关系,并为联系人可能涉及的每个实体创建一个Map表,如:

CREATE TABLE [dbo].[Contacts] (
    [Id]         INT            IDENTITY (1, 1) NOT NULL,
    [Name]       NVARCHAR (80)  NULL,
    [Email]      NVARCHAR (80)  NULL,
    [Phone]      NVARCHAR (80)  NULL,
    [Title]      NVARCHAR (80)  NULL,
    [Address]    NVARCHAR (120) NULL
);

CREATE TABLE [dbo].[ContactCustomers] ( 
    [ContactId]  INT NOT NULL REFERENCES Contacts([ContactId]),
    [CustomerId] INT NOT NULL REFERENCES Customers([CustomerId]),
    PRIMARY KEY([ContactId], [CustomerId])
);

CREATE TABLE [dbo].[ContactProviders] ( 
    [ContactId]  INT NOT NULL REFERENCES Contacts([ContactId]),
    [ProviderId] INT NOT NULL REFERENCES Providers([ProviderId]),
    PRIMARY KEY([ContactId], [ProviderId])      
);

CREATE TABLE [dbo].[ContactLocations] ( 
    [ContactId]  INT NOT NULL REFERENCES Contacts([ContactId]),
    [LocationId] INT NOT NULL REFERENCES Locations([LocationId]),
    PRIMARY KEY([ContactId], [LocationId])      
);

这使您在关系方面具有充分的灵活性,同时保持 Contacts 表的主要用途是:存储与此实体相关的数据。

baubqpgj

baubqpgj2#

除了@gmb的建议之外,另一种选择是简单地拥有不同的联系表。仅仅因为地点和客户都有联系人,而且它们最初具有相同的属性,并不意味着它们必须存储在同一个表中。
如果您不打算查询所有联系人,那么像这样单独存储它们会更有效。三者的模式可能会随着时间的推移而发生分歧。
如果您想在联系人类型上编写公共逻辑,它们甚至可以在应用程序中共享一个notmapped超类contact。

CREATE TABLE [dbo].[CustomerContacts] (
    [CustomerId] INT            not null references Customer on delete cascade,
    [Id]         INT            IDENTITY (1, 1) NOT NULL,
    [Name]       NVARCHAR (80)  NULL,
    [Email]      NVARCHAR (80)  NULL,
    [Phone]      NVARCHAR (80)  NULL,
    [Title]      NVARCHAR (80)  NULL,
    [Address]    NVARCHAR (120) NULL,
    constraint pk_CustomerContacts primary key (CustomerId,Id)
);
CREATE TABLE [dbo].[ProviderContacts] (
    [ProviderId] INT            not null references Provider on delete cascade,
    [Id]         INT            IDENTITY (1, 1) NOT NULL,
    [Name]       NVARCHAR (80)  NULL,
    [Email]      NVARCHAR (80)  NULL,
    [Phone]      NVARCHAR (80)  NULL,
    [Title]      NVARCHAR (80)  NULL,
    [Address]    NVARCHAR (120) NULL,
    constraint pk_ProviderContacts primary key (ProviderId,Id)
);
CREATE TABLE [dbo].[LocationContacts] (
    [LocationId] INT            not null references Location on delete cascade,
    [Id]         INT            IDENTITY (1, 1) NOT NULL,
    [Name]       NVARCHAR (80)  NULL,
    [Email]      NVARCHAR (80)  NULL,
    [Phone]      NVARCHAR (80)  NULL,
    [Title]      NVARCHAR (80)  NULL,
    [Address]    NVARCHAR (120) NULL,
    constraint pk_LocationContacts primary key (LocationId,Id)
);
vmdwslir

vmdwslir3#

联系人是对客户、提供商和地点的概括。这里有一些技巧你可能会发现很有用。共享主键和类表继承。

相关问题