1

我的 SQL 数据库 (Firebird) 有一个名为tTransaction的表。它包含两列,senderFKreceiverFK。还有其他三个表,tBufferStocktFacilitytOutsideLocation

发送方或接收方可以是缓冲库存、我们自己的设施或外部位置。

我的问题是我不知道如何让senderFKreceiverFK引用正确的表。

我已经想到了发送者和三个可能的发送者之间的一个新表,该表具有一个 ID、一个介于 1 和 3 之间的数字以及该表中引用的 ID,但实际上这并不能解决问题。有任何想法吗?

诺伯特

4

4 回答 4

2

您尝试做的事情无法在 SQL 中完成。您不能使用单个 FK 最多引用三个不同的表。

你需要做的是:

  • 创建额外的列senderBufferstockFK, senderFacilityFK, 和senderOutsideLocationFK
  • 将它们连接到适当的表
  • 在主表上有一个检查约束(如果支持)或触发器或其他一些机制,以确保在任何给定时间只有这三个中的一个具有值

这意味着,在任何给定时间,三个“fk”列中只有一个可以有一个值,但每个 FK 列都是特定表的特定 FK。

您可以将其直接放入您正在谈论的表中,或者您可以将其外部化到单独的表中,并从您的主表中仅引用该“中间”表,然后从那里获得这三个 FK

YourTable.SenderFK --> Intermediary.PK
    Intermediary.SenderBufferstockFK --> tBufferstock.ID
    Intermediary.SenderFacilityFK --> tFacility.ID
    Intermediary.SenderOutsideLocationFK --> tOutsideLocation.ID

或者您可以放弃 FK 关系,但这绝对不是一个好主意!

马克

于 2009-10-23T12:39:19.570 回答
1

尝试以下架构:

tSenderReceiver (type INT, id INT, PRIMARY KEY (type, id))

tTransaction (id INT PRIMARY KEY, senderType INT, senderId INT, receiverType INT, receiverID INT,
      FOREIGN KEY (senderType, senderID) REFERENCES tSenderReceiver,
      FOREIGN KEY (receiverType, receiverID) REFERENCES tSenderReceiver
)

tBufferStock (type INT, id INT,
      CHECK (type = 1),
      PRIMARY KEY (type, id),
      FOREIGN KEY (type, id) REFERENCES tSenderReceiver
)

tFacility (type INT, id INT,
      CHECK (type = 2),
      PRIMARY KEY (type, id),
      FOREIGN KEY (type, id) REFERENCES tSenderReceiver
)

tOutsideLocation (type INT, id INT,
      CHECK (type = 3),
      PRIMARY KEY (type, id),
      FOREIGN KEY (type, id) REFERENCES tSenderReceiver
)
于 2009-10-23T12:46:06.593 回答
1

SQL 不支持“表 X 中的这一列或表 Y 中的那一列”形式的外键。你可以:

  1. 重构您的数据库,以便将所有三个可能的外键表合并为一个,可能称为 tCounterParty。如果这些表的结构相同或非常相似,这绝对是合适的。如果它们不相似,您仍然可以采用这种方法并使用链接到 tCounterParty 的其他三个表来保存不同的信息。

  2. 如果数据库支持,将引用完整性从外键移到触发器中。

于 2009-10-23T12:48:19.910 回答
0

你不能用 3 列作为发送者,3 列作为接收者吗?因此您将拥有 bufferSenderFK、facilitySenderFK 和 facilitySenderFK。对于单个事务,可以使用 1 列,其他两列将为空。

于 2009-10-23T12:43:27.473 回答