Eviter les doublons lors de l'insertion dans la BD

Petit nouveau ! | 3 Messages

23 oct. 2006, 15:42

Bonjour,

Je suis débutant (comme bcp de monde) en php/mysql et j'espère trouver ici un début de piste à la solution de mon problème. :roll:

J'ai crée un site (vitrine web pour une boutique) avec plusieurs "produits" dans la base de données.

J'ai crée un formulaire pour ajouter facilement de nouveaux produits à la base de données et bien sur avant introduction dans la BD, j'aimerais que les informations soient vérifiés.

Ainsi j'ai réussi à coder un ch'tit quelquechose pour prévenir l'utilisateur quand certains champs du formulaire étaient vides.

Par contre je sèche sur la méthode à utiliser pour éviter qu'un produit portant le même nom qu'un autre ne soit ajouté en double dans la base de données.

La table s'appelle "produits" et le nom des objets se trouve dans la colone "Nomproduits".

Merci de votre aide.

Ps: J'ai tenté ca mais ca ne fonctione pas... :(
$nom est la variable recuiellit par le formulaire dans laquelle est stockée la valeur entrée par l'utilisateur pour le nom du produit.

Code : Tout sélectionner

$test = mysql_query("SELECT * FROM produits WHERE Nomproduits='$nom'"); if ($nom == $test) { echo ("Ce produit existe déjà dans la base de données"); exit; }

Modérateur PHPfrance
Modérateur PHPfrance | 6037 Messages

23 oct. 2006, 16:02

Il te suffit d'ajouter un index de type UNIQUE sur le champ que tu souhaites unique.

Par ailleurs, dans ton code tu fais une requête, et MySQL te renvoie un bundle de résultats...tu dois d'abord traiter ce pack.
Règle n°2 du webmaster : Toujours commencer par le HTML qu'on veut obtenir....toujours ! :priere:
J'aime apprendre de nouvelles choses.

Avatar du membre
Modérateur PHPfrance
Modérateur PHPfrance | 10684 Messages

23 oct. 2006, 16:08

C'est normal que cela ne fonctionne pas, ta variable $test contient une ressource mysql (c'est à dire l'ensemble des colonnes et des lignes vérifiant les conditions de ta requête) ... tu ne peux donc pas la comparer directement au nom de ton produit :)

A ta place, je remplacerais le "SELECT * " par un "SELECT COUNT(*) " afin de compter le nombre d'enregistrements correspondant. Si le résultat est différent de zéro, c'est que l'élément fait doublon (ou plus :))

Nota : le résultat du "select count" est également une ressource mysql qu'il faut récupérer avec un mysql_fetch_* pour la comparer :)
Ce n'est pas en améliorant la bougie que l'on a inventé l'ampoule...

Eléphant du PHP | 193 Messages

23 oct. 2006, 16:08

Si ton produit existe déjà (du moins si le nom de ce produit est déjà utilisé), ta requête te renverra au moins une ligne, regarde du côté de mysql_num_rows.

Cela ne t'empêche absolument pas de mettre l'index UNIQUE, au contraire, c'est la seule sécurité qui empêchera réellement que deux produits aient le même nom.

Modérateur PHPfrance
Modérateur PHPfrance | 2575 Messages

23 oct. 2006, 16:28

Il te suffit d'ajouter un index de type UNIQUE sur le champ que tu souhaites unique.

Par ailleurs, dans ton code tu fais une requête, et MySQL te renvoie un bundle de résultats...tu dois d'abord traiter ce pack.
La solution de mere-teresa est la meilleure, car si on est développeur on n'est pas simplement programmeur surtout quand on développe autours d'une base de données.
Et pour bien expliquer les choses : SQL prévoit déjà la technique "index unique" pour fixer une contrainte d'unicité d'enregistrement dans une table, il suffit donc de déclarer ton champ comme éttant un index unique par SQL au niveau de la base.
Côté programmation, le programmeur lui ne se souci plus de comment tester l'unicité car en lançant une requête INSERT ou UPDATE c'est le SGBD qui s'occupe de ce test avant l'acceptation de la requête.

C'est ce qui correspond à ton besoin, tu dois alors te contenter de soumettre ton INSERT/UPDATE et s'il y a echec tu recevras du SGBD le message d'erreur équivalent.

Par contre si ton programme veut effectivement vérifier l'existance d'un enregistrement dans le cadre d'une recherche, là oui, tu doit utiliser une requête SELECT avec un WHERE (comme tu fais) et là les réponses des autres amis sont claires, ton code est mal écrit car il faut d'abord lire le résultat de mysql_query() avec un mysql_fetch... pour accèder à l'information qui peut exister ou pas.
Comme ça par exemple :
<?php
//résultat de la recherche
$produit = mysql_query("SELECT Nomproduits FROM produits WHERE Nomproduits='".trim($nom)."'"); 
 
//test si le nom est trouvé
 if (($row = mysql_fetch_assoc($produit)) { //si au moins une ligne est retournée par le résultat $produit
 echo ("Ce produit existe déjà dans la base de données"); 
 exit; 
 }
?>
Ceci dit, même si tu optes pour la solution recherche avec SELECT, la proposition de mere-teresa n'est pas optionnelle mais une obligation vis-à-vis des règles du modèle de données puisque tu le présente comme tel.
Modifié en dernier par sadeq le 23 oct. 2006, 16:39, modifié 2 fois.
--------//////----//---//----//////
-------//---//----//---//----//---//
------//////----//////-----//////
-----||--------||--||---||
Prendre le recul n'est pas une perte de temps.


ps: Affrontez moi dans l'arène

Avatar du membre
Modérateur PHPfrance
Modérateur PHPfrance | 10684 Messages

23 oct. 2006, 16:38

Beuh moi chuis pas fan de cette façon de faire... alors bien sur je suis à fond pour la contrainte d'unicité pour préserver l'intégrité, mais je préfère vérifier qu'un enregistrement existe plutôt que d'essayer de l'inserer en force et de gérer l'erreur qu'il me retourne.. même si c'est l'une des principales vocations des blocs try/catch..

C'est un peu plus lourd et redondant sans doute, mais sur le principe j'aime pas considérer l'erreur comme un fonctionnement normal de l'appli qui sera du coup traité d'une manière spécifique et non pas comme une erreur...

M'enfin ça n'engage que moi :)
Ce n'est pas en améliorant la bougie que l'on a inventé l'ampoule...

Petit nouveau ! | 3 Messages

23 oct. 2006, 16:45

Merci pour vos réponses constructives.

En effet je ne savais pas comment exploiter le résultat d'une requete SELECT, donc là ca va beaucoup mieux.

Ma solution finale (ca fonctionne):
 $test = mysql_query("SELECT * FROM produits WHERE produitsNom='$nom'");
 $verdict = mysql_fetch_array($test, MYSQL_ASSOC);
 if ($nom == $verdict['produitsNom'])
 { echo "Ce produit existe déjà dans la base de données<br>";
 exit;
 }
J'ai aussi ajouté un index de type unique sur le champ "produitsNom", en fait comme le dit sadeq cette solution était suffisante.
Mais j'ai quand même rajouté le petit bout de code qui permet d'informer l'utilisateur. C'est un peu plus propre, et ca ma permis de progresser :wink:
Merci à tous, je reviendrais surement vous embeter bientôt :D

Modérateur PHPfrance
Modérateur PHPfrance | 6037 Messages

23 oct. 2006, 16:52

A noter que les index rendent les requêtes sur les champs indexés plus rapides !
Règle n°2 du webmaster : Toujours commencer par le HTML qu'on veut obtenir....toujours ! :priere:
J'aime apprendre de nouvelles choses.