【问题标题】:MSSQL - Foreign key to the same column IF other column is not equal to the referring rowMSSQL - 如果其他列不等于引用行,则同一列的外键
【发布时间】:2017-02-01 10:34:39
【问题描述】:

我有一个数据库,其中有两个表:

CREATE TABLE Transactions (
    ID BIGINT IDENTITY(1,1) NOT NULL,
    AccountID BIGINT NOT NULL,
    Amount BIGINT NOT NULL,
    CONSTRAINT PK_Transactions PRIMARY KEY CLUSTERED (ID ASC,AccountID ASC),
    CONSTRAINT FK_Transaction_Account FOREIGN KEY (AccountID) REFERENCES Accounts(ID)
);
CREATE TABLE Accounts (
    ID BIGINT IDENTITY(1,11) NOT NULL,
    Balance BIGINT NOT NULL,
    CONSTRAINT PK_Accounts PRIMARY KEY (ID)
);

交易通过我编写的存储过程插入到他们的表中,因此当账户 1 将 25 个“硬币”转移到账户 21 时会生成 行:

 ID | AccountID | Amount
-------------------------
 1  | 1         | -25
-------------------------
 1  | 21        | 25

在上述架构中,我希望第一行根据 ID 引用底行,并且 AccountID 不等于 到底行的 AccountID。
反之亦然。

我想要做的看起来像这样:

CONSTRAINT FK_Transaction_Counterpart FOREIGN KEY (ID) REFERENCES Transactions(ID) WHERE thisRow.AccountID != referencedRow.AccountID

我在关于表格约束的文档中没有发现这种可能性。
因此,出于好奇和使用它的意图,我问,这可能吗?如果是,如何?

编辑:

答案表明这是不可能的,我应该调整我的设计或意图。
我想我会在功能代码中将两个事务行相互分配。

【问题讨论】:

    标签: sql-server database-design foreign-keys constraints


    【解决方案1】:

    传统的外键不能是有条件的(即没有附加 WHERE 子句)。在您的情况下,我可能只是确保插入是原子的(在同一个事务中),这样就不可能只插入其中一个。

    【讨论】:

      【解决方案2】:

      如果您尝试实现的数据模型是:

      • 一个事务 (ID) 在表 Transactions 中有两个且只有两个条目
      • 对于给定 Transaction ID 的两行,AccountID 不能相同

      那么,您可以在数据库表结构中执行此业务规则的一种可能过于复杂的方法如下:

      Accounts,正如你所定义的

      Transactions,正如你所定义的

      新表 TransactionPair 带有:

      列(全部不为空)

      • ID

      • LowAccountID

      • HighAccountID

      约束

      • ID 上的主键(每个交易 ID 只有一个条目)
      • 将(ID、LowAccountID)外键输入事务
      • 将(ID、HighAccountID)外键导入事务
      • 检查行上的约束,使得LowAccountID < HighAccountID

      流程:

      • 将一对行添加到事务表中
      • 将单行添加到引用刚刚添加的行的 TransactionPair
      • 如果无法添加该行,则失败,将所有内容回滚

      看起来很整洁,但很可能过于复杂。您的里程可能会有所不同。

      【讨论】:

        猜你喜欢
        • 2018-05-29
        • 2016-05-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-12-30
        • 1970-01-01
        相关资源
        最近更新 更多