为几个表之一设计外键
Designing foreign keys to one of several tables
我有三个 table:Customers
、Providers
和 Locations
。我需要创建第四个 table,名为 Contacts
。
我希望有任意数量的 Contacts
与 Customers
、Providers
和 Locations
table 中的任何行相关联,所以我结束了想出这样的东西。
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
.
另一种方法是创建多对多连接 table。这不需要任何未使用的列。但这似乎仍然是一种浪费,因为任何联系人都不会与不止一家公司相关。
有人知道任何更巧妙的解决方案吗?
另一种方法是恢复关系,并为联系人可能涉及的每个实体创建一个映射 table,例如:
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
table 专注于其主要目的:存储与此实体相关的数据。
除了@GMB 的建议外,另一种选择是简单地使用不同的联系人 table。仅仅因为 Locations 和 Customers 都有联系人,并且仅仅因为它们最初具有相同的属性,并不意味着它们必须存储在相同的 table 中。
如果您不打算查询所有联系人,像这样单独存储它们会更有效。随着时间的推移,这三者的模式可能会有所不同。
如果您想在联系人类型上编写通用逻辑,他们甚至可以在应用程序中共享联系人的 NotMapped 超类。
EG
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)
);
联系人是客户、提供商和位置的概括。您可能会发现这里有一些有用的技巧。 shared-primary-key and class-table-inheritance.
我有三个 table:Customers
、Providers
和 Locations
。我需要创建第四个 table,名为 Contacts
。
我希望有任意数量的 Contacts
与 Customers
、Providers
和 Locations
table 中的任何行相关联,所以我结束了想出这样的东西。
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
.
另一种方法是创建多对多连接 table。这不需要任何未使用的列。但这似乎仍然是一种浪费,因为任何联系人都不会与不止一家公司相关。
有人知道任何更巧妙的解决方案吗?
另一种方法是恢复关系,并为联系人可能涉及的每个实体创建一个映射 table,例如:
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
table 专注于其主要目的:存储与此实体相关的数据。
除了@GMB 的建议外,另一种选择是简单地使用不同的联系人 table。仅仅因为 Locations 和 Customers 都有联系人,并且仅仅因为它们最初具有相同的属性,并不意味着它们必须存储在相同的 table 中。
如果您不打算查询所有联系人,像这样单独存储它们会更有效。随着时间的推移,这三者的模式可能会有所不同。
如果您想在联系人类型上编写通用逻辑,他们甚至可以在应用程序中共享联系人的 NotMapped 超类。
EG
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)
);
联系人是客户、提供商和位置的概括。您可能会发现这里有一些有用的技巧。 shared-primary-key and class-table-inheritance.