База данных SQL (Firebird): проблема с внешним ключом - PullRequest
1 голос
/ 23 октября 2009

В моей базе данных SQL (Firebird) есть таблица с именем tTransaction . Он содержит два столбца: senderFK и receiveFK . Есть еще три таблицы: tBufferStock , tFacility и tOutsideLocation .

Отправителем или получателем может быть либо буферный запас, либо наше собственное предприятие, либо местоположение за пределами.

Моя проблема в том, что я не знаю, как позволить senderFK или receiveFK ссылаться на нужную таблицу.

Я подумал о новой таблице между отправителем и тремя возможными отправителями с идентификатором, числом от 1 до 3 для таблицы и ссылочным идентификатором в этой таблице, но на самом деле это не решает проблему. Есть идеи?

Norbert

Ответы [ 4 ]

2 голосов
/ 23 октября 2009

То, что вы пытаетесь сделать, не может быть сделано в 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-отношений, но это определенно НЕ хорошая идея!

Марк

1 голос
/ 23 октября 2009

SQL не поддерживает внешний ключ в форме «ни этот столбец в таблице X, ни этот столбец в таблице Y». Вы можете:

  1. Рефакторинг вашей базы данных, чтобы все три возможные таблицы внешних ключей были объединены в одну, возможно, называемую tCounterParty. Это определенно уместно, если структура этих таблиц идентична или очень похожа. Если они не похожи, вы все равно можете воспользоваться этим подходом и использовать три другие таблицы, связанные с tCounterParty, для хранения различной информации.

  2. Переместите ссылочную целостность из внешнего ключа в триггер, если это поддерживается вашей базой данных.

1 голос
/ 23 октября 2009

Попробуйте следующую схему:

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
)
0 голосов
/ 23 октября 2009

вы не можете использовать 3 столбца для отправителя и 3 для получателя? таким образом, вы будете иметь буфер SenderFK, средство SenderFK и средство SenderFK. для одной транзакции можно использовать 1 столбец, а два других будут нулевыми.

...