2010-02-04 5 views
0

У меня есть таблица, которая управляет виртуальными папками загрузки для сайта.Ограничение внешнего ключа (сложный?)

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) не может ссылаться на два разных поля. Что вы можете предложить, чтобы мои предложенные ограничения работали?

+0

Я не понимаю, зачем вам нужны внешние ключи. Одного только одного должно быть достаточно, чтобы убедиться, что запись ссылается на действительную комбинацию папок/сайтов. – friedo

ответ

0

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

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

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

+0

@friedo: спасибо, но я уже использую InnoDB с иностранными ключами. Я обновил свой вопрос, чтобы более четко сформулировать проблему (надеюсь). Не могли бы вы еще раз взглянуть на это? Благодарю. –

0

Вы можете это сделать, если вы используете механизм хранения 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; 

Это не проверить его, но он должен работать. См. FOREIGN KEY Constraints.

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

+0

@Felix: спасибо, но я уже использую InnoDB с иностранными ключами. Я обновил свой вопрос, чтобы более четко сформулировать проблему (надеюсь). Не могли бы вы еще раз взглянуть на это? Благодарю. –

Смежные вопросы