2010-06-03 5 views
1

Ce problème me donne un vrai mal de tête.Supprimer avec JOIN?

J'ai deux tables dans ma base de données qui résout le tri des catégories à l'aide d'un design appelé "table de fermeture". La première table est appelée categories et l'autre est nommée categoriesPaths.

Catégories est tout simplement une table basée sur le langage:

id | name 
---------------- 
0 | Category 1 
1 | Category 2 

CategoriesPaths ressemble à ceci:

parent | children | level 
----------------------- 
1  | 1   | 0 
1  | 2   | 1 
2  | 2   | 0 

Pour supprimer un chemin ensemble avec ses nœuds enfants éventuels, j'exécutez la requête suivante: ($ top est le niveau de nœud parent supérieur à partir duquel la suppression commencera)

DELETE d FROM CategoriesPaths children 
JOIN CategoriesPaths a USING (children) 
WHERE a.parent = $top; 

Ce que je voulais t à faire est changer la requête pour supprimer également les chemins représentatifs dans la table categories. Malheureusement, je n'ai pas assez de connaissances SQL pour le faire. J'ai essayé de faire une solution de contournement avec une boucle de foreach avant la requête, mais cela ne parvient pas à supprimer, puisque la table categories est référencée à categoriesPaths ... Cela dit, je suis bloqué.

Si quelqu'un veut en savoir plus sur la conception de la table de fermeture, voici une référence à la SlideShare où je l'ai appris de: http://www.slideshare.net/billkarwin/sql-antipatterns-strike-back

Répondre

1

Pourquoi ne pas utiliser une transaction? http://www.firstsql.com/tutor5.htm

+0

J'utilise des transactions aux requêtes, mais pas montré dans cet exemple, car je ne vois pas comment cela pourrait affecter le résultat de la requête? (En supposant que la requête doit être faite en une seule étape) – Industrial

+1

@Industrial Avec une transaction, vous pouvez éliminer toutes les jointures de votre sql, en émettant un ensemble de requêtes séparées. Il supprime une partie de la complexité et garantit également que votre base de données reste cohérente en annulant les modifications en cas d'échec. –

2

Eh bien, je prendrais un autre chemin.

  1. Créer une table temporaire avec les id de tous les éléments à supprimer
  2. CategoriesPaths Supprimer de la table temporaire
  3. Supprimer Catégories de table temporaire
  4. Supprimez la table temporaire.

Comme ceci:

-- not tested 
CREATE TABLE tmp_to_delete 
AS SELECT children.children 
FROM CategoriesPaths children 
JOIN CategoriesPaths a USING (children) 
WHERE a.parent = $top; 

DELETE FROM CategoriesPaths WHERE children IN (SELECT children FROM tmp_to_delete) 
DELETE FROM Categories WHERE id IN (SELECT children FROM tmp_to_delete) 

DROP TABLE tmp_to_delete