8796 sujets

Développement web côté serveur, CMS

Bonjour,

J'aimerais supprimer un certain nombre d'enregistrements dans de multiples tables toutes liées entre elle à partir d'une seule information. Ma requête passe mais n'affecte aucun enregistrement. Pourriez vous m'aider?

Voici la requête:
delete cat_id id, cat_rel rel, bCat_config bg, sCat_config sg, cat_status cs, cat_images ci, images i
		from cat_id id, cat_rel rel, bCat_config bg, sCat_config sg, cat_status cs, cat_images ci, images i
		where
		id.ref_cat='/*ici je transmet la référence d'une grande catégorie*/' 
		and rel.ref_bCat=id.ref_cat
		and bg.ref_cat=id.ref_cat
		and sg.ref_cat=rel.ref_cat
		and cs.ref_cat=rel.ref_cat and cs.ref_cat=id.ref_cat
		and ci.ref_sCat=rel.ref_cat
		and i.ref_image=ci.ref_sCat


Et voici la structure de mes tables:
CREATE TABLE IF NOT EXISTS `bCat_config` (
  `ref_cat` char(10) NOT NULL default '',
  `outFocus` char(14) default NULL,
  PRIMARY KEY  (`ref_cat`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;

-- --------------------------------------------------------

--
-- Structure de la table `cat_id`
--

CREATE TABLE IF NOT EXISTS `cat_id` (
  `ref_cat` varchar(10) NOT NULL default '',
  `ctype` enum('s','b') NOT NULL default 's',
  `nom` varchar(30) default NULL,
  `image` varchar(14) default NULL,
  `onFocus` varchar(14) NOT NULL default '',
  PRIMARY KEY  (`ref_cat`),
  KEY `type` (`ctype`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;

-- --------------------------------------------------------

--
-- Structure de la table `cat_images`
--

CREATE TABLE IF NOT EXISTS `cat_images` (
  `ref_image` char(10) NOT NULL default '',
  `ref_sCat` char(10) default NULL,
  PRIMARY KEY  (`ref_image`),
  KEY `byCat` (`ref_sCat`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;

-- --------------------------------------------------------

--
-- Structure de la table `cat_rel`
--

CREATE TABLE IF NOT EXISTS `cat_rel` (
  `ref_cat` char(10) NOT NULL default '',
  `ref_bCat` char(10) NOT NULL default '',
  PRIMARY KEY  (`ref_cat`),
  KEY `ref_bCat` (`ref_bCat`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;

-- --------------------------------------------------------

--
-- Structure de la table `cat_status`
--

CREATE TABLE IF NOT EXISTS `cat_status` (
  `ref_cat` char(10) NOT NULL default '',
  `status` enum('0','1') NOT NULL default '0',
  PRIMARY KEY  (`ref_cat`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;

-- --------------------------------------------------------

--
-- Structure de la table `images`
--

CREATE TABLE IF NOT EXISTS `images` (
  `ref_image` varchar(10) NOT NULL default '',
  `mini` varchar(50) default NULL,
  `image` varchar(50) default NULL,
  `position` tinyint(2) default NULL,
  PRIMARY KEY  (`ref_image`),
  KEY `position` (`position`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;

-- --------------------------------------------------------

--
-- Structure de la table `sCat_config`
--

CREATE TABLE IF NOT EXISTS `sCat_config` (
  `ref_cat` char(10) NOT NULL default '',
  `outFocus` char(14) default NULL,
  `onFocus` char(14) default NULL,
  PRIMARY KEY  (`ref_cat`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;


Je pense que le problème vient de l'ordre des conditions dans Where, mais je n'ai pas confirmation. Actuellement, je commence par supprimer le haut de la pyramide, pour ainsi dire, donc l'identité de l'élément parent absolu visé. Dans la mesure où tout se situe dans une seule requête delete, je n'en suis pas certain, mais peut être devrais je commencer par éliminer les éléments dont aucune donnée ne dépend (comme les images) avant d'éliminer l'élément dont dépend toute l'expression, non?

En vous remerciant de vos lumières^^

Smoke
Modifié par Smoke (22 Oct 2009 - 14:03)
S'il s'agit de supprimer une certaine ligne d'une table et toutes les lignes liés sur d'autres tables, reliés à la première par des clés étrangères, je pense qu'il pourrait être intéressant de te tourner vers le moteur InnoDB et sa gestion de l'intégrité référencielle, en conjonction avec les triggers si tu peux / si ton hébergement le permet.

En l'état, pour dire, honnêtement, c'est bien la première fois que je vois une requête delete qui porte simultanément sur plusieurs tables. a mon avis, c'est pas possible.
Salut QuentinC et merci de l'attention que tu portes à mon problème^^

En fait, le delete multitables est possible, je l'ai utilisé dans mon projet, mais il s'agissait d'une suppression n'impliquant que deux ou trois tables.

Pour l'utilisation de InnoDB, ça va être trop compliqué pour moi d'y passer, j'en suis encore à Myisam et phpmyadmin, qui ne facilite pas la tâche pour les clefs étrangères de Innodb. De plus, je sais pas si mon hébergeur me permet en effet tout ça^^ c'est d'un niveau largement supérieur au mien donc j'ai jamais testé.

En revanche, j'ai vérifié en inversant les clauses du where, et ça ne fonctionne pas plus -_-
InnoDB ne posera pas de problème pour ton hébergeur et phpmyadmin. La transition est facile et sans danger normalement. C'est forcément supporté, en tout cas pour mysql 4 et plus.

Bon, j'avoue, je ne connais pas très bien phpmyadmin, il est trop mal foutu pour moi, je préfère largement utiliser mysql directement en ligne de commande ou avec un script perso ultra simplifié.

Ce qui n'est peut-être pas autorisé, c'est les triggers. IL n'y a pas beaucoup d'hébergeurs qui les autorisent.
De même, je te proposerais bien d'utiliser des vues, mais ton hébergeur ne les autorise peut-être pas plus. IL faut se renseigner, mais ça simplifierait sûrement ton truc.

Quant à parler de clés étrangères, myIsam ne les gère absolument pas. En réalité si tu as mis des contraintes ou des instructions foreign key dans ton create table, ils sont ignorés avec le moteur MyIsam.
Pour les foreign keys et myisam, je suis au courant Smiley smile , donc je n'en ai mise aucune. Disons que ma clef ref_cat se retrouve partout en fait^^ (sauf dans la table images).

Côté triggers et utilisation des clefs étrangères, je suis pas du tout calé. Je crains de n'avoir à opter pour une solution un peu cracra, à savoir faire ça en plusieurs requêtes, vu que je suis en fin de projet ça me permettra d'éviter à avoir à reprendre trop de choses^^. Qu'en penses tu?

(cela dit si quelqu'un est en mesure de m'aider à corriger ma fichue requête, je suis preneur...)
Voici la doc pour le delete unique et multiple:
http://dev.mysql.com/doc/refman/5.1/en/delete.html

J'ai déjà trouvé une façon d'améliorer ma requête: supprimer les noms de tables entre delete et from. Cette syntaxe sert quand on utilise des tables pour chercher les résultats et qu'on ne supprime pas dans les mêmes tables, ce qui n'est pas mon cas^^

De plus, les alias ne devront être mentionnés qu'à partir de from
Modifié par Smoke (22 Oct 2009 - 15:42)
La requête suivante fonctionne presque:

delete rel, id, cs, sg, ci, i, bg
		from cat_rel as rel
			inner join cat_id as id on id.ref_cat=rel.ref_cat
			inner join cat_status as cs on cs.ref_cat=rel.ref_cat
			inner join sCat_config as sg on sg.ref_cat=rel.ref_cat
			inner join cat_images as ci on ci.ref_sCat=rel.ref_cat
			inner join images as i on i.ref_image=ci.ref_image
			left outer join bCat_config as bg on bg.ref_cat='fd822d544c'
		where rel.ref_bCat='fd822d544c' or rel.ref_cat='fd822d544c' and id.ref_cat='fd822d544c' and cs.ref_cat='fd822d544c'


elle ne me supprime que 17 enregistrements, alors qu'elle devrait en supprimer environ 36. En dehors des suppressions omises, elle ne fait aucune erreur, les enregistrements supprimés sont tous des cibles visées. A l'évidence, j'ai un soucis de jointures maintenant Smiley lol mais on progresse!
Bon, j'suis passé en InnoDB finalement, j'ai refait ma structure en essayant de tout faire correctement, mais au remplissage de mes tables ça fonctionne mal. Pourrais tu m'aider?