2016-09-23 42 views
0

我有一个数据库中,我有两个表:MSSQL - 外键同一列,如果其他列不等于指行

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和帐户ID的第一行以引用的底部行正在不等于到底行的AccountID。
而且反之亦然。

我想做的事情会是这个样子什么:

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

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

编辑:

答案反映,这是不可能的,我应该调整我的设计或意图。
我想我会解决在功能代码中将两个事务行分配给对方。

回答

1

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

1

如果你想实现的数据模型是:

  • 一个交易(ID)有两个,只有两个表中交易项
  • 给定事务ID的两行时,AccountIDs不能是同

然后一个也许过于复杂的方式,你可以执行数据库表结构中此业务规则将如下所示:

Accounts,正如你所定义

Transactions,正如你所定义

新表TransactionPair有:

列(均为NOT NULL)

  • ID

  • LowAccountID

  • HighAccountID

约束

    上ID
  • 主键上(ID,LowAccountID)(每交易ID只有一个条目)
  • 外键交易
  • 外键( ID,HighAccountID)转换成交易
  • 检查行上的约束,使LowAccountID < HighAccountID

过程:

  • 添加对行的交易表
  • 添加单排TransactionPair引用刚才添加
  • 如果不能添加该行的行,东西失败了,滚一切恢复

看起来很整齐,但很可能过于复杂。你的旅费可能会改变。