我有一个数据库结构,其中包括下表:
CREATE TABLE dbo.PaymentProvidersForEntities
(
PaymentProviderId SMALLINT NOT NULL,
EntityId BIGINT NOT NULL,
CONSTRAINT PK_PaymentProvidersForEntities
PRIMARY KEY (PaymentProviderId, EntityId),
CONSTRAINT FK_PaymentProvidersForEntities_PaymentProviders
FOREIGN KEY (PaymentProviderId)
REFERENCES PaymentProviders(PaymentProviderId)
ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT FK_PaymentProvidersForEntities_Entities
FOREIGN KEY (EntityId)
REFERENCES Entities(EntityId)
ON DELETE CASCADE ON UPDATE CASCADE
)
显然,这是一个带有复合主键的简单多对多链接表。我想要另一个表,该表引用该表但仅提供一个 PaymentProvider 的数据(即 PaymentProviderId = 固定值)。就像是:
CREATE TABLE dbo.SpecificPaymentProviderExtraDetails
(
EntityId BIGINT NOT NULL,
ExtraDetails NVARCHAR(MAX) NOT NULL,
CONSTRAINT PK_PaymentProviderExtraDetails
PRIMARY KEY (EntityId),
CONSTRAINT FK_PaymentProviderExtraDetails_PaymentProvidersForEntities
FOREIGN KEY (EntityId, 1)
REFERENCES PaymentProvidersForEntities(EntityId, PaymentProviderId)
ON DELETE CASCADE ON UPDATE CASCADE
)
显然,我可以在 PaymentProvidersForEntities 表中添加一个可为 null 的“ExtraDetails”字段,但我觉得这不是很优雅,因为会有几种不同类型的支付提供商,每个都需要不同类型的额外细节。有没有一种优雅的方式来做我想做的事?如果没有,那么实现相同目标的更好方法是什么?
最佳答案
最简单的方法是存储支付提供商 ID,并使用 CHECK() 约束来确保它是您想要的。假设您希望支付提供商 ID 始终等于 13。
CREATE TABLE dbo.PaymentProviderExtraDetails
(
PaymentProviderID SMALLINT NOT NULL DEFAULT 13 CHECK(PaymentProviderID = 13),
EntityId BIGINT NOT NULL,
ExtraDetails NVARCHAR(MAX) NOT NULL,
CONSTRAINT PK_PaymentProviderExtraDetails
PRIMARY KEY (PaymentProviderID, EntityId),
CONSTRAINT FK_PaymentProviderExtraDetails_PaymentProvidersForEntities
FOREIGN KEY (PaymentProviderID, EntityID)
REFERENCES PaymentProvidersForEntities(PaymentProviderId, EntityId)
ON DELETE CASCADE ON UPDATE CASCADE
);
我更喜欢这种方法而不是持久化列,因为这种方法遵循 principle of least surprise 。扩展以支持两个、三个或四个支付提供商而不是一个支付提供商也更简单。
如果我是你,我会重新考虑表名。它可能应该以您为其记录数据的单一支付提供商命名。
关于sql - 使用外键,我可以在复合主键中引用固定值吗?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/14630192/