2016-09-23 48 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引用剛纔添加
  • 如果不能添加該行的行,東西失敗了,滾一切恢復

看起來很整齊,但很可能過於複雜。你的旅費可能會改變。