Page 1 sur 2
Injection SQL depuis un CSV...
Posté : 27 déc. 2011, 09:45
par FURAX69
Bonjour à tous,
Voila, je dois injecter des data dans une base SQL, mais je dois enrichir des enregistrements existants et non pas simplement en ajouter (ce que je maitrise).
Je dois lire un fichier CSV (issue d'Excel) dans lequel, j'ai un numéro de compte et un budget. Chaque fiche déjà présente dans la BDD contient un champ
avec ce même numéro de compte et je dois renseigner le champ budget de la BDD au moyen de cette importation...
Je sais que c'est possible, mais je ne vois pas comment faire... Et plus je parcours le web, moins je trouve...
Si quelqu'un peux m'aider ce serais très sympa
Merci d'avance,
Thierry
Re: Injection SQL depuis un CSV...
Posté : 27 déc. 2011, 10:00
par Mazarini
Pour mettre à jour des enregistrements, il faut daire un UPDATE au lieu d'un INSERT.
Re: Injection SQL depuis un CSV...
Posté : 27 déc. 2011, 10:15
par moogli
Salut,
le terme d'injection SQL est ici mal choisit en règle générale il s'agit d'une excploitation de faiblesse des requêtes (via la non sécurisation de formulaire) pour "pirater un serveur".
Dans ton cas tu peux regarder du côté du replace de mysql mais Perso je m'orienterais vers une procédure stockée à de. Paramètres. Cette procédure fait un sélect count pour savoir si la ligne existe, si oui iodate si non insert.
Je te conseil aussi l'utilisation de pdo et des requêtes préparée.
@+
Re: Injection SQL depuis un CSV...
Posté : 27 déc. 2011, 12:17
par FURAX69
Pour mettre à jour des enregistrements, il faut daire un UPDATE au lieu d'un INSERT.
Ca je le sais... Mais comment faire des update sélectifs sur une clé trouvée et dans la BDD et dans mon fichier CSV ?
Re: Injection SQL depuis un CSV...
Posté : 27 déc. 2011, 12:18
par FURAX69
Salut,
Dans ton cas tu peux regarder du côté du replace de mysql mais Perso je m'orienterais vers une procédure stockée à de. Paramètres. Cette procédure fait un sélect count pour savoir si la ligne existe, si oui iodate si non insert.
Je te conseil aussi l'utilisation de pdo et des requêtes préparée.

@+
Rien compris de tout ça... Mais je vais chercher...
Re: Injection SQL depuis un CSV...
Posté : 27 déc. 2011, 12:54
par Mazarini
Je suppose que tu sais lire le fichier.
Il faut faire une tentative d'update avec les données lues et regarder combien de lignes modifiées - mysql_affected_rows() - et faire l'insert si pas de lignes modifiée.
Une option est de commencer par l'insert et de faire un update en cas d'erreur duplicate key.
Re: Injection SQL depuis un CSV...
Posté : 27 déc. 2011, 14:13
par moogli
Hum tu va être obliger d'indiquer comment capturer les erreurs
Plus sérieusement, pour plus d'info sur SQL =>
sqlpro sur développez.com.
Une procédure stockée ce n'est pas compliqué à mettre en oeuvre
Pour pdo
http://www.php.net/pdo
@+
Re: Injection SQL depuis un CSV...
Posté : 27 déc. 2011, 15:21
par Mazarini
Pour capturer les erreurs : mysql_errno()
Re: Injection SQL depuis un CSV...
Posté : 27 déc. 2011, 16:00
par moogli
avec la niveau d'erreur adéquat sinon E_WARNING ?
enfin s'pa grave y a deux possibilités a exploiter la
@+
Re: Injection SQL depuis un CSV...
Posté : 27 déc. 2011, 21:48
par AB
Je suppose que tu sais lire le fichier.
Il faut faire une tentative d'update avec les données lues et regarder combien de lignes modifiées - mysql_affected_rows() - et faire l'insert si pas de lignes modifiée.
Une option est de commencer par l'insert et de faire un update en cas d'erreur duplicate key.
Heu... n''est-ce pas là tout l'intérêt de la syntaxe : INSERT INTO ... ON DUPLICATE KEY UPDATE
Avec ça tu fais l'équivalent de tes deux requêtes en une seule.
Re: Injection SQL depuis un CSV...
Posté : 28 déc. 2011, 10:02
par FURAX69
Merci de vos réponses, mais étant débutant, je n'ai pas compris grand chose...
Rien de plus parlant qu'un exemple de code, donc si quelqu'un sait où je peux trouver ça ?
Re: Injection SQL depuis un CSV...
Posté : 28 déc. 2011, 23:49
par moogli
heu
http://dev.mysql.com/doc/refman/5.0/en/ ... icate.html ?
1er lien de
cette recherche
sinon pour la méthode avec procédure stockée
La table de test:
CREATE TABLE `furax69` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`numero` int(11) NOT NULL,
`budget` decimal(8,2) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=latin1
La procédure Stockée
-- --------------------------------------------------------------------------------
-- Routine DDL
-- --------------------------------------------------------------------------------
DELIMITER $$
CREATE DEFINER=`root`@`localhost` PROCEDURE `procFurax69`(
IN num INT,
IN bud decimal(10,2),
out ret boolean)
BEGIN
declare nb int;
declare tmp boolean;
set @tmp := false;
select count(*) into nb from furax69 where numero = num ;
if nb = 0 then
insert into furax69 (numero,budget) value(num,bud);
set @tmp := true;
else
update furax69 set budget=bud where numero = num;
set @tmp := true;
end if;
select @tmp into ret;
END$$
DELIMITER ;
Le code php avec PDO
<?php
$fichiercsv = file('furax69.csv');
try {
$pdo = new PDO("mysql:host=localhost;dbname=test;charsey=utf8","root","yyRu2TKEvyYpzFLK");
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$stmt = $pdo->prepare('call procFurax69(:numero,:budget,@sortie)');
foreach($fichiercsv as $line){
$csv = str_getcsv($line, ';');
/*
$num = 12;
$bud = 45550.52;
*/
$stmt->bindParam(':numero', $csv[0], PDO::PARAM_INT);
$stmt->bindParam(':budget', $csv[1], PDO::PARAM_INT);
//$stmt->bindParam(':sortie', $retour, PDO::PARAM_STR,5);
$stmt->execute();
$s = $pdo->query('select @sortie')->fetch(PDO::FETCH_OBJ);
echo 'La procédure à retourné : ', $s->{'@sortie'};
}
}
catch (PDOException $e){
echo '<pre style="word-wrap:break-word;">';
echo $e->getMessage();
echo '</pre>';
}
?>
Le fichier de test
Code : Tout sélectionner
123456;45789.8
456789;789.5
7832;486.48
159753;486.58
458652;965.12
546;456.25
456.15;48996.52
résultat
Code : Tout sélectionner
mysql> select * from furax69;
+----+--------+----------+
| id | numero | budget |
+----+--------+----------+
| 1 | 123456 | 45789.80 |
| 2 | 456789 | 789.50 |
| 3 | 7832 | 486.48 |
| 4 | 159753 | 486.58 |
| 5 | 458652 | 965.12 |
| 6 | 546 | 456.25 |
| 7 | 456 | 48996.52 |
+----+--------+----------+
7 rows in set (0.00 sec)
un tuto sur les procédure stockée pour mysql
un tuto sur PDO
Ce code à le mérite d'être a peux prêt standard, donc fonctionnel quelque soit le SGBD
@+
Re: Injection SQL depuis un CSV...
Posté : 29 déc. 2011, 05:01
par AB
Je vois pas trop l'intérêt d'une procédure stockée. En même temps comme je n'ai pas encore eu à les utiliser... ceci explique peut-être cela
Y a-t-il a un avantage de ce système par rapport à un tout bête :
$req = "INSERT INTO furax69 (numero,budget)
VALUES ('123456','45789.8')
ON DUPLICATE KEY UPDATE
budget = VALUES(budget)
";
dans cet exemple il suffit que "numero" soit déclaré comme unique et ça devrait aller, non ?
ah oui je viens de trouver l'avantage de ton code : il doit être compatible PostgreSQL alors que le mien ne doit fonctionner qu'avec mysql.
Bah finalement, il reste encore des avantages à travailler avec mysql alors
(Et c'est pas demain que je vais changer car mes code sont truffés de INSERT INTO ... ON DUPLICATE KEY UPDATE (car c'est hyper pratique))
Re: Injection SQL depuis un CSV...
Posté : 29 déc. 2011, 10:32
par Mazarini
Travailler avec des procédures stockées permet de sortir le SQL du PHP et de n'avoir que les procédures stockées à modifier pour porter d'un système à l'autre.
Re: Injection SQL depuis un CSV...
Posté : 29 déc. 2011, 12:37
par moogli
Exactement c'est une couche de plus pour séparer logique métier de l'affichage
Ceci dit si le code est voué à rester sur mysql ce n'est pas problème.
Après je n'ai pas regarder en détails le on duplicate key, la question qui me vient c'est : ça se passe lorsque la clef unique n'est pas la clef primaire ? (j'imagine un numéro de compte alphanumérique et une clef auto incrémenté )?
@+