Ограничение внешнего ключа (сложное?) - PullRequest
0 голосов
/ 04 февраля 2010

У меня есть таблица, которая управляет виртуальными папками загрузки для сайта.

CREATE TABLE `folder` (
  # id = PK
  `id` int(10) unsigned NOT NULL auto_increment,
  # folderId = self referencing FK to id
  `folderId` int(10) unsigned default NULL,
  # siteId = FK to id in site table
  `siteId` int(10) unsigned NOT NULL
)

В идеале мне нравится siteId для ссылки id в таблице site, но также есть составная FK folderId, siteId для самостоятельной ссылки на id, siteId в таблице folder.

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

Возможно ли что-то подобное? Если так, то как? А если нет, есть ли у вас другие предложения, как я могу гарантировать это состояние?

EDIT:
Извините, я должен был упомянуть об этом раньше: я знаю о InnoDB, и фактически я уже использую его (вместе с внешними ключами). Но вопрос в том, как я смогу гарантировать эти две вещи:

  • Запись в folder должна ссылаться на действительный site с siteId
  • Запись в folder также должна совпадать с siteId с родительской записью (только если она, конечно, дочерняя)

Я пробовал это до сих пор:

  # this one should guarantee folder belongs to
  # a valid site (this one works of course)
  CONSTRAINT `FK_folder_site_1`
    FOREIGN KEY (`siteId`)
    REFERENCES `site` (`id`) ON UPDATE CASCADE,

  # this one should guarantee child folder belongs to
  # the same site as parent folder (doesn't work)
  CONSTRAINT `FK_folder_folder_1`
    FOREIGN KEY `FK_folder_folder_1` (`folderId`, `siteId`)
    REFERENCES `folder` (`id`, `siteId`) ON DELETE CASCADE ON UPDATE CASCADE

Так что последний не работает (конечно?), Потому что кажется логичным, что внешний ключ (siteId) не может ссылаться на два разных поля. Что вы можете предложить, чтобы мои предложенные ограничения работали?

Ответы [ 2 ]

0 голосов
/ 04 февраля 2010

Вы можете сделать это, если используете механизм хранения InnoDB

CREATE TABLE `folder` (
  # id = PK
  `id` int(10) unsigned NOT NULL auto_increment,
  # folderId = self referencing FK to id
  `folderId` int(10) unsigned default NULL,
  # siteId = FK to id in site table
  `siteId` int(10) unsigned NOT NULL,
  FOREIGN KEY (folder_id, site_id) REFERENCES folder(id, site_id)
) ENGINE=INNODB;

Это не проверялось, но должно работать. См. ЗАРУБЕЖНЫЕ КЛЮЧЕВЫЕ КЛЮЧИ .

Если вы хотите / должны использовать MyISAM, конечно, вы можете сделать это логически так же, как вы делаете это с «обычными» ограничениями внешнего ключа.

0 голосов
/ 04 февраля 2010

Механизм хранения InnoDB поддерживает внешние ссылки с самостоятельными ссылками, и вы можете использовать их для эмуляции иерархической структуры. Чтобы объявить ключ, вы можете сделать что-то вроде этого в своем выражении CREATE TABLE:

FOREIGN KEY (`folderId`,`siteId`) REFERENCES `folder` (`Id`, `siteId`)

Важно помнить, что этот ключ должен иметь возможность NULL, чтобы вы могли указать, какие записи являются корнем дерева.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...