4

我有一个数据库结构,其中包括下表:

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 表中添加一个可为空的“ExtraDetails”字段,但我觉得这不是很优雅,因为会有几种不同类型的支付提供商,每一种都需要不同类型的额外细节。有没有一种优雅的方式来做我想做的事?如果不是,那么实现相同目标的更好方法是什么?

4

3 回答 3

2

最简单的方法是存储支付提供商 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
);

我更喜欢这种方法而不是持久列,因为这种方法遵循最不意外的原则。扩展到支持两个、三个或四个支付提供商而不是一个也更简单。

如果我是你,我会重新考虑表名。它可能应该以您为其记录数据的单一支付提供商命名。

于 2013-01-31T17:20:51.847 回答
1

您可以将持久计算列添加到引用列列表:

CREATE TABLE dbo.p(i1 INT, i2 INT, CONSTRAINT p_pk PRIMARY KEY CLUSTERED (i1,i2));
CREATE TABLE dbo.c(id INT PRIMARY KEY CLUSTERED,i1 INT, i2 AS 1 PERSISTED, CONSTRAINT c_fk FOREIGN KEY (i1,i2) REFERENCES dbo.p(i1,i2));
INSERT INTO dbo.p(i1,i2)VALUES(42,1);
INSERT INTO dbo.c(id,i1)VALUES(111,42);
于 2013-01-31T16:56:15.863 回答
-1

如果您的第二个表的主键是代理键,并且您为您想要的复合键部分创建一个外键,它将为您完成。

例如,伪sql

foo
bar int primarykey
foobar int primarykey

测试
testFoo int
primarykey foobar int foriengkey

只要确保你只把你想要的项目放在测试中。如果你真的想要安全,你可以限制foobar确保它只有你想要的值

于 2013-01-31T16:50:43.720 回答