Page 1 sur 1

Inserer sans doublon

Posté : 21 mars 2011, 18:57
par fabulon
Bonjour,
Je fais une insertion d'un fichier csv dans une base sql.
Je souhaite que lorsque l'utilisateur fasse une nouvelle insertion dans la base, ne soit pris en compte que les nouvelles lignes du csv, et pas celles déja présentes dans la table.

J'ai lu au gré des mes recherches que l'on pouvait faire un insert into suivi d'un select.
Mais je ne comprends pas comment ça marche pour l'adapter...

Si vous pouviez me donner un exemple...
Merci!

Re: Inserer sans doublon

Posté : 21 mars 2011, 21:13
par fabulon
Je mets mon code qui ne fonctionne pas du tout:
- si la table est vide au départ, il ne fait rien (mais j'ai compris pourquoi)
- si la table n'est pas vide, il m'insère uniquement la 1ere ligne du csv, et ce, autant de fois qu'il y a de lignes dans la table! C'est pas trop ce que je veux!
                $requete2="SELECT * from magret"; // requête proprement dite 
		$result2 = mysql_query($requete2) or die(mysql_error()); // envoi de la requête 
		
		$handle = fopen ($directory.'magret.csv',"r");
		while ($data = fgetcsv ($handle, 0, ":")) {
			if ($data[0] != 'PROF') {
				while($row = mysql_fetch_array($result2)) {
				echo $row['CLASSE'];
				
					if (($row['CLASSE'] != '$data[0]') || ($row['NOM'] != '$data[1]') || ($row['PRENOM'] != '$data[2]') || ($row['LOGIN'] != '$data[4]') || ($row['MDP'] != '$data[6]') ) {
					$requete = "INSERT INTO magret (classe,nom,prenom,login,mdp,uid_ent) VALUES ('$data[0]','$data[1]','$data[2]','$data[4]','$data[6]','')";
					$result = mysql_query($requete) or die(mysql_error()); 
					}
				}
			}
		}	
		
		fclose ($handle);

Re: Inserer sans doublon

Posté : 21 mars 2011, 22:57
par moogli
http://dev.mysql.com/doc/refman/5.0/fr/replace.html ?

Sinon le problème de ton algo c'est que tu ne parcourt le résultat mysql qu'une seul fois car lorsque qu'une fois que le jeux d'enregistrement est parcourut n'est pas "remis" à zéro donc cela ne fonctionne qu'une seule fois.
donc soit tu ajoute un mysql_data_seek dans la boucle tu fichier

soit tu inverse les deux boucles.

Dans les deux cas je pense qu'utiliser un tableau pour la boucle su milieux sera peut être plus performant (à vérifier ;) ).

@+

Re: Inserer sans doublon

Posté : 21 mars 2011, 23:04
par fabulon
J'ai modifié mon fichier entre temps:
$requete2="SELECT * from magret"; // requête proprement dite 
		$result2 = mysql_query($requete2) or die(mysql_error()); // envoi de la requête 
		
		$handle = fopen ($directory.'magret.csv',"r");
		while ($data = fgetcsv ($handle, 0, ":")) {
			if ($data[0] != 'PROF') {
				$count='0';
				echo $count;
				while($row = mysql_fetch_array($result2)) {
					if (($row['CLASSE'] == $data[0]) && ($row['NOM'] == $data[1]) && ($row['PRENOM'] == $data[2]) && ($row['LOGIN'] == $data[4]) && ($row['MDP'] == $data[6]) ) $count=$count++;
					}
				if ($count =='0') {
				$requete = "INSERT INTO magret (classe,nom,prenom,login,mdp,uid_ent) VALUES ('$data[0]','$data[1]','$data[2]','$data[4]','$data[6]','')";
				$result = mysql_query($requete) or die(mysql_error()); 
				}
			}
		}	
		
		fclose ($handle);
Mais je ne comprends pas pourquoi il ne boucle qu'une fois.
Pour moi, voilà ce qu'il fait:
il regarde la 1ere ligne du csv ( while ($data = fgetcsv ($handle, 0, ":")) { )
puis il regarde si cette ligne se retrouve dans la table. Si c'est le cas il incrémente mon compteur.
Si le compteur est resté à 0, il inserère la ligne dans la table.
Puis il recommence avec la 2nde ligne. etc...

Non?

Re: Inserer sans doublon

Posté : 21 mars 2011, 23:17
par moogli
je verrais plutôt ça sans compteur ^^

Un peu comme ça :
<?php
$requete2="SELECT * from magret"; // requête proprement dite
$result2 = mysql_query($requete2) or die(mysql_error()); // envoi de la requête
$handle = fopen ($directory.'magret.csv',"r");
while ($data = fgetcsv ($handle, 0, ":")) {
	if ($data[0] != 'PROF') {
		$count='0';
		echo $count;
		while($row = mysql_fetch_array($result2)) {
			if (($row['CLASSE'] == $data[0]) && ($row['NOM'] == $data[1]) && ($row['PRENOM'] == $data[2]) && ($row['LOGIN'] == $data[4]) && ($row['MDP'] == $data[6]) ) {
				$requete = "INSERT INTO magret (classe,nom,prenom,login,mdp,uid_ent) 
				VALUES ('${data[0]}','${data[1]}','${data[2]}','${data[4]}','${data[6]}','')";
				$result = mysql_query($requete);
				if ($result === false) {
					echo mysql_error().'<br />';
				}
			}
		}
	}
	mysql_data_seek($result2,0);
}      
fclose ($handle);
?>
Après coté perf je en sais pas si parcourir X fois un résultat mysql est plus performant que de parcourir X fois un tableau ;)


@+

Re: Inserer sans doublon

Posté : 21 mars 2011, 23:59
par fabulon
Ca ne marche pas: pas d'erreur (sauf si l'on part d'une table vide, mais ça ça se corrige), mais pas non plus d'enregistrement sauf si on contraire il trouve les mêmes lignes. Alors il les insère x fois...

Re: Inserer sans doublon

Posté : 22 mars 2011, 00:02
par stealth35
met bien les index UNIQUE ensuite fait juste un INSERT IGNORE
je te conseil aussi de vite passer a mysqli ou PDO

Re: Inserer sans doublon

Posté : 22 mars 2011, 00:07
par fabulon
Je ne peux pas mettre des index unique, car je peux avoir des champs identiques.
En revanche, je ne veux pas avoir de lignes identiques.
Est-ce compatible avec index unique?

Re: Inserer sans doublon

Posté : 22 mars 2011, 00:46
par stealth35
oui, tu peux mettre plusieurs champs dans ton INDEX
http://dev.mysql.com/doc/refman/5.0/fr/ ... index.html

Re: Inserer sans doublon

Posté : 22 mars 2011, 21:43
par fabulon
Que faut-il rajouter sur ma création de table pour que les 5er champs soient uniques, mais pas individuellement?
CREATE TABLE IF NOT EXISTS `magret` (
	`CLASSE` varchar(10) NOT NULL,
	`NOM` varchar(30) NOT NULL,
	`PRENOM` varchar(30) NOT NULL,
	`LOGIN` varchar(7) NOT NULL,
	`MDP` varchar(30) NOT NULL,
	`UID_ENT` varchar(20) NULL DEFAULT NULL
	) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE latin1_swedish_ci
Autrement dit les lignes
1,1,1,1,1,1
1,1,1,1,1,2 doivent être considérées comme des doublons
mais pas
1,1,1,1,1,1
1,2,1,1,1,1 par exemple...

Re: Inserer sans doublon

Posté : 23 mars 2011, 11:16
par fabulon
C'est bon, j'ai fini par trouver...

J'ai rajouté une ligne sur la création de ma table:
CREATE TABLE IF NOT EXISTS `magret` (
	`CLASSE` varchar(10) NOT NULL,
	`NOM` varchar(30) NOT NULL,
	`PRENOM` varchar(30) NOT NULL,
	`LOGIN` varchar(7) NOT NULL,
	`MDP` varchar(30) NOT NULL,
	`UID_ENT` varchar(20) NULL DEFAULT NULL,
	UNIQUE (`CLASSE` , `NOM` , `PRENOM` , `LOGIN` , `MDP`)
	) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE latin1_swedish_ci
Et en ce qui concerne l'insertion des lignes, j'ai mis l'option ignore:
$requete = "INSERT IGNORE INTO magret (classe,nom,prenom,login,mdp,uid_ent) VALUES ('$data[0]','$data[1]','$data[2]','$data[4]','$data[6]','')";
Merci pour votre aide!