Вопрос

В моей базе данных SQL (Firebird) есть таблица с именем tТранзакция.Он содержит два столбца, отправительFK и приемникFK.Есть еще три стола, tBufferStock, tОбъект и tOutsideLocation.

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

Моя проблема в том, что я не знаю, как позволить отправительFK или приемникFK обратитесь к правой таблице.

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

Норберт

Это было полезно?

Решение

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

Марк

Другие советы

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

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 не поддерживает внешний ключ вида «либо этот столбец в таблице X, либо этот столбец в таблице Y».Ты можешь:

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top