2010-02-04 6 views
0

J'ai une table qui gère les dossiers de téléchargement virtuel pour un site.Contrainte de clé étrangère (complexe?)

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 
) 

Idéalement j'aime siteId faire référence id dans le tableau site, mais également un composé FK folderId, siteId être auto référencement à id, siteId dans le tableau folder.

La raison pour laquelle je veux ceci est que je veux garantir qu'un dossier enfant appartient toujours au même site que le dossier parent.

Est-ce quelque chose comme cela possible? Si c'est le cas, comment? Et si non, avez-vous d'autres suggestions sur comment je peux garantir cet état?

EDIT:
Désolé, je l'ai mentionné plus tôt: je sais InnoDB, et en fait, je l'utilise déjà (avec les clés étrangères). Mais la question est, comment vais-je être en mesure de garantir ces deux choses:

  • Un record folder doit faire référence valide site avec siteId
  • Un record folder doit également être le même siteId que le dossier parent (seulement si elle est un enfant bien sûr)

J'ai essayé jusqu'à présent:

# 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 

Donc le dernier ne fonctionne pas (bien sûr?) Car il semble logique qu'une clé étrangère (siteId) ne puisse pas référencer deux champs différents. Que pouvez-vous suggérer pour que mes contraintes proposées fonctionnent?

+0

Je ne vois pas pourquoi vous avez besoin des deux clés étrangères. Le second seul devrait suffire à garantir qu'un enregistrement fasse référence à une combinaison dossier/site valide. – friedo

Répondre

0

Le moteur de stockage InnoDB prend en charge les clés étrangères autoréférencées et vous pouvez les utiliser pour émuler une structure hiérarchique. Pour déclarer la clé, vous pourriez faire quelque chose comme ça dans votre déclaration CREATE TABLE:

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

Une chose importante à retenir est que cette clé devrait être NULL able, vous pouvez indiquer quel enregistrement (s) sont la racine de l'arbre.

+0

@friedo: merci, mais j'utilise déjà InnoDB avec des clés étrangères. J'ai mis à jour ma question pour énoncer le problème plus clairement (j'espère). Cela vous dérangerait-il d'y jeter un autre coup d'oeil? Merci. –

0

Vous pouvez le faire si vous utilisez le moteur de stockage 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; 

Il n'a pas testé mais il devrait fonctionner. Voir FOREIGN KEY Constraints.

Si vous voulez/devez utiliser MyISAM, vous pouvez bien sûr le faire logiquement de la même manière que vous le faites avec les contraintes de clé étrangère "normales".

+0

@Fixix: merci, mais j'utilise déjà InnoDB avec des clés étrangères. J'ai mis à jour ma question pour énoncer le problème plus clairement (j'espère). Cela vous dérangerait-il d'y jeter un autre coup d'oeil? Merci. –

Questions connexes