Question

My SQL database (Firebird) has a table named tTransaction. It contains two columns, senderFK and receiverFK. There are three other tables, tBufferStock, tFacility and tOutsideLocation.

A sender or a receiver can be either a buffer stock, our own facility or a location outside.

My problem is that I don't know how to let senderFK or receiverFK reference the right table.

I've thought of a new table between sender and the three possible senders with an ID, a number between 1 and 3 for the table and the referenced ID within this table, but actually that doesn't solve the problem. Any ideas?

Norbert

Was it helpful?

Solution

What you're trying to do cannot be done in SQL. You cannot reference up to three different tables with a single FK.

What you need to do would be:

  • create additional columns senderBufferstockFK, senderFacilityFK, and senderOutsideLocationFK
  • connect those to the appropriate tables
  • have a check constraint (if supported) or a trigger or some other mechanism on your main table to make sure only one of those three has a value at any given time

This would mean, at any given time, only one of the three "fk" column could have a value on it, but each FK column would be a specific FK to a specific table.

You could put this directly into the table you're talking about, or you could externalize this into a separate table and from your main table just reference that "intermediary" table, and from there have these three FK

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

Or you can just drop the FK-relationship, but that's definitely NOT a good idea!

Marc

OTHER TIPS

Try the following schema:

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
)

SQL does not support a foreign key of the form "either this column in table X or that column in table Y". You can:

  1. Refactor your database so that all three possible foreign key tables are combined into one, possibly called tCounterParty. This is definitely appropriate if the structure of those tables is identical or very similar. If they are not similar you can still take this approach and use three other tables, linked to tCounterParty, to hold the varying information.

  2. Move your referential integrity from a foreign key into a trigger, if supported by your database.

can't you use 3 columns for sender and 3 for receiver? so you'll have bufferSenderFK, facilitySenderFK and facilitySenderFK. for a single transaction, 1 column can be used and other two will be null.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top