IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

PHP & Base de données Discussion :

Comparer ligne csv et ligne table SQL


Sujet :

PHP & Base de données

  1. #1
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2019
    Messages
    8
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2019
    Messages : 8
    Par défaut Comparer ligne csv et ligne table SQL
    Bonjour,

    J'aurai besoin d'aide ou de pistes pour un problème à priori simple mais je bloque pas mal dessus. (Je suis encore débutant en php/mysql)
    Je dois remplir une table de ma base de données sous MySQL en important les données d'un fichier .csv (c'est OK, j'ai réussi) mais avant de faire cet import, il me faut comparer les données de ma première ligne, deuxième, troisième etc ... jusqu'à la fin du fichier csv (qui correspond aux noms des colonnes qu'il doit y avoir dans ma table) avec le nom des colonnes de ma table sous MySQL afin de vérifier que nous avons un bon ordonnancement et que nous mettons les bonnes données aux bons endroits.

    Mais voilà je patauge, je n'arrive pas à récupérer une par une les données de ma ligne1, ligne 2, ligne 3 etc ... puis la comparer à la colonne adéquate de ma table.

    Voici ce que je voudrais :

    J'ai une requête préparée :
    Code PHP : Sélectionner tout - Visualiser dans une fenêtre à part
     $bdd -> prepare ('SELECT fld_nom FROM td_tables WHERE fld_nom = ?')

    Ce bout de code ne doit sûrement pas marcher mais c'est un exemple de ce que je voudrais ...
    Code PHP : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    while($champ = fgetcsv($fic,$taille,$delimiteur)){
    $ref_nom = $champ[1]; //ligne de la colonne "nom" du fichier csv
    $req_compare_csv -> execute([$_POST['table']]);
     
    //echo $result['fld_nom'];
     
    while ($result = $req_compare_csv->fetch()){
                    $refdb=$result['fld_nom'];
    //Si ligne 1 BDD == ligne 1 CSV alors "OK" et on passe à la ligne 2 : Si ligne 2 BDD == ligne 2 CSV alors "OK" etc ... 
                        if ($refdb==$ref_nom){
                        echo "OK";
                        }
                        else {
                        echo "NOK";
                        }
                 }
    }
    fclose ($fic);
    EDIT : En fait en me relisant je ne suis pas très clair, en résumé je voudrais comparer seulement une colonne "nom" de mon fichier CSV et la colonne "nom" de ma table SQL.
    Exemple :
    Dans ma table Animal : Colonne Nom_Animal :
    Chien, Chat, Lapin,Cheval
    Dans mon fichier CSV : Colonne Nom_Animal :
    Chien, fourmi, serpent,dauphin

    Je veux simplement comparer toutes les lignes avant d'importer mes données, du coup : Chien et Chien "OK", on continue -> Chat et fourmi "NOK" on arrête la lecture et on resélectionne un autre fichier où les noms doivent être identiques à la colonne nom de la table SQL.
    (J'espère avoir été assez clair... Sinon n'hésitez pas à me poser des questions !)
    Auriez-vous des pistes ? Merci d'avance

  2. #2
    Membre éprouvé
    Profil pro
    Inscrit en
    Juin 2010
    Messages
    73
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2010
    Messages : 73
    Par défaut
    Ce n'est pas très clair pour moi, en tout cas...

    1. Quelle est la volumétrie ? Le traitement ne sera pas forcément le même si tu as trois éléments que si tu en as 42 millions.

    2. Mettons-nous d'accord :
    - Le fichier CSV, tu veux l'utiliser pour faire un INSERT massif ou c'est pour un UPDATE ?
    - Que compares-tu au juste ?
    - Une table d'une base de données n'est pas "triée". On ne peut donc pas comparer une table et un CSV ligne à ligne.
    A la limite, on peut comparer le résultat d'une requête triée et un CSV...

    J'ai compris ça :
    Table ANIMAUX :
    Nom_Animal Information_Animal
    Chien fait ouaf
    Chat feignant
    Cheval fait des lasagnes
    Fichier CSV :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    Chien;fait ouaf
    Fourmi;croonde
    Chat;fainéant
    Et tu veux que :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    SI (un animal présent dans le CSV est absent de la TABLE) OU (un animal présent dans la TABLE est absent du CSV)
       ERREUR
    SINON
       Traitement

  3. #3
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2019
    Messages
    8
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2019
    Messages : 8
    Par défaut
    Bonjour !

    Le fichier CSV est pour un UPDATE dans la base de données.

    > Une table d'une base de données n'est pas "triée". On ne peut donc pas comparer une table et un CSV ligne à ligne.
    A la limite, on peut comparer le résultat d'une requête triée et un CSV...

    Oui pardon, voici ma vraie requête :
    Code PHP : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     $req_compare_csv = $bdd -> prepare ('
    							SELECT fld_nom 
    							FROM td_fields 
    							WHERE fld_tbl_id = ( 
    							SELECT tbl_id 
    							FROM td_tables 
    							WHERE tbl_nom = ? ) 
    							ORDER BY fld_ordre
    							');

    Donc oui ma table est triée et j'aimerai comparer 1 à 1 les résultats de la colonne "fld_nom" à la colonne "nom" de mon fichier CSV également trié.
    Donc ce que je voudrais est :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    if (colonne_fldnomSQL != colonneNomCSV){
    erreur }
    else {
    //Les colonnes sont égales on importe les données
    }
    EDIT : En fait j'ai plusieurs table de la même famille dans lesquelles on retrouve cette fameuse colonne "nom". Dans cette colonne il arrive parfois que le nom réapparaisse dans certaines tables et à la même position.
    Par exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    Table_Animal 1 : 
    (position, nom)
    1;Chien
    2;Chat
    3;Lapin
     
    Table_Animal2 :
    (position,nom)
    1;Chien
    2;Chat
    3;Cheval
     
    Fichier_CSV :
    (position,nom)
    1;Chien
    2;Chat
    3;Cheval
    Je veux simplement vérifier que le fichier CSV appartienne bien à la table_animal2.

    Merci d'avance pour la lecture de mon problème !

  4. #4
    Membre éprouvé
    Profil pro
    Inscrit en
    Juin 2010
    Messages
    73
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2010
    Messages : 73
    Par défaut
    Il faut qu'il y ait exactement la même chose de chaque côté, quoi...

    Dans ce cas, la solution la plus simple est de stocker le résultat de ta requête dans un tableau.
    Ensuite tu lis chaque ligne de ton CSV et tu compares avec l'élément du tableau. Et tu peux t'arrêter à la première erreur, histoire d'optimiser un peu...
    En gros :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    TANT QUE LitLigneCSV
       if ResultatSQL[i] != Champ1
          return FALSE
       i = i + 1
    FIN TQ
    return TRUE

  5. #5
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2019
    Messages
    8
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2019
    Messages : 8
    Par défaut
    @MacGawel : Merci beaucoup ! Ca marche
    Par contre dans le return FALSE j'aimerai bien écrire un petit mot du genre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    if($tableau_nom_SQL[$i] !== $champ[1]){
    							echo "Attention votre fichier ne correspond pas à la table demandée"
    						}$i++;
    Mais évidemment vu que c'est dans le "tant que" ça m'envoie en boucle le message. Et comme le "else" dans une boucle while ne fonctionne pas ... Une idée ?
    Merci encore ! =)

  6. #6
    Membre éprouvé
    Profil pro
    Inscrit en
    Juin 2010
    Messages
    73
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2010
    Messages : 73
    Par défaut
    Je l'ai écrit comme une fonction qui renvoie TRUE ou FALSE. Derrière, tu peux traiter le retour et afficher ton message suivant le résultat...

    Si tu veux "juste" afficher ton message et sortir de ta boucle, utilise break.

  7. #7
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2019
    Messages
    8
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2019
    Messages : 8
    Par défaut
    Mince ... Finalement ce n'est pas le résultat que je voulais. Ta méthode marche bien pour comparer et lire chaque ligne. Cependant j'aurai plutôt voulu que ça lise toutes les lignes d'abord et ensuite updater mon fichier csv dans la table.
    C'est à dire que même si la 1ère ligne / 2ème ligne / 3ème ligne etc... correspondent bien mais que la 15ème ligne ne correspond pas alors on update pas le fichier dans cette table car il faut que toutes les lignes correspondent.

    Code PHP : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
     
    while($champ = fgetcsv($fic,$taille,$delimiteur)){
    							$ref_nom = $champ[1];
    						//echo $champ[1] . "<br/>";
     
    						//On vérifie si les résultats de la reqûete_2 correspondent bien aux résultats du libellés "nom" dans le fichier CSV.
    							if($tableau_nom_SQL[$i] !== $ref_nom){
    								echo "Attention votre fichier ne correspond pas a la table demandee";
    								break;
    							}$i++;
    							$update_data = $bdd -> exec ('
    								UPDATE td_fields
    								SET fld_lib ="' . (utf8_encode($champ[2]))) .'", fld_description = "'. (utf8_encode($champ[3])) . '"
    								WHERE fld_ordre = "'. $champ[0] .'"
    								AND fld_nom = "'. $champ[1] .'" 
    								AND fld_tbl_id = (
    								SELECT tbl_id FROM td_tables
    								WHERE tbl_nom = "' . $_POST['table'] .'")
     
    								');
    						}//echo "Les donnees ont bien ete importees.";
    						fclose($fic);
     
    				}
    EDIT : En gros, récupérer toute la colonne du fichier CSV , il faut donc que toute la colonne CSV soit égale à toute la colonne de la table SQL / au résultat de la requête. On va y arriver

  8. #8
    Membre éprouvé
    Profil pro
    Inscrit en
    Juin 2010
    Messages
    73
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2010
    Messages : 73
    Par défaut
    Tu as deux solutions :

    1.
    Procéder en deux étapes :
    - D'abord tu compares toutes les lignes du CSV avec la table.
    - Puis SI c'est ok tu fais l'update.
    Dans ce cas, la plupart des BDD te permettent d"importer un fichier CSV, ça peut être intéressant au lieu de boucler pour faire N updates.

    2. Utiliser les fonctionnalités de ta BDD :
    - Tu ouvres ta transaction SQL.
    - Tu boucles sur le CSV, en faisant les updates à chaque ligne (ce que tu fais, quoi).
    - SI une ligne du CSV n'est pas OK => tu demandes un RollBack à ta table et tu arrêtes le traitement.
    SI tout s'est bien passé => tu fais le Commit.
    L'intérêt de cette méthode, c'est que tu laisses la BDD tout gérer. Elle est même capable de t'engueuler si tu essayes d'updater "Fourmi" alors qu'il n'existe pas

  9. #9
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2019
    Messages
    8
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2019
    Messages : 8
    Par défaut
    Justement le but est de créer une fonctionnalité (l'import de fichier) pour certains utilisateurs n'ayant accès à phpmyadmin .
    Du coup ta première solution sera plus convenable à ce que je voudrai
    > - D'abord tu compares toutes les lignes du CSV avec la table.
    Toutes les lignes tu veux dire les lignes de la colonne "nom" en question ? Si oui c'est pas ce que j'avais fait ?
    Code PHP : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     while($champ = fgetcsv($fic,$taille,$delimiteur)){
    							$ref_nom = $champ[1];
     
    						//On vérifie si les résultats de la reqûete_2 correspondent bien aux résultats du libellés "nom" dans le fichier CSV.
    							if($tableau_nom_SQL[$i] !== $champ[1]){
    								echo "Attention votre fichier ne correspond pas a la table demandee";
    								break;
    							}$i++;
    Le problème c'est que pour comparer un fichier CSV et le résultat de ma requête il faudra toujours mettre le while =/

    > Puis SI c'est ok tu fais l'update.
    Oui c'est ce que je voulais faire en quelque sorte :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    TANT QUE LitLigneCSV
       if ResultatSQL[i] != Champ1
          return FALSE
       i = i + 1
       else Update
    FIN TQ
    Mais comme je l'avais dit tout à l'heure on peut pas mettre de else dans le while =/

  10. #10
    Membre éprouvé
    Profil pro
    Inscrit en
    Juin 2010
    Messages
    73
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2010
    Messages : 73
    Par défaut
    Citation Envoyé par bibi76 Voir le message
    Justement le but est de créer une fonctionnalité (l'import de fichier) pour certains utilisateurs n'ayant accès à phpmyadmin .
    Du coup ta première solution sera plus convenable à ce que je voudrai
    > - D'abord tu compares toutes les lignes du CSV avec la table.
    Toutes les lignes tu veux dire les lignes de la colonne "nom" en question ? Si oui c'est pas ce que j'avais fait ?
    Le mot important était d'abord
    Citation Envoyé par bibi76 Voir le message
    Le problème c'est que pour comparer un fichier CSV et le résultat de ma requête il faudra toujours mettre le while =/
    Tu as besoin de savoir si le fichier est "correct" avant de démarrer les updates.
    Il te faut donc deux étapes :
    1. Tu vérifies que le fichier est correct par rapport à ta table (avec une boucle WHILE).
    2. SI il est correct (je parle de tout le fichier) tu fais les updates (avec une seconde boucle WHILE).

    Pour rester sur ta méthode, ça donnerait :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    i = 0
    FichierOK = True
    ResultatSQL = "SELECT Nom FROM MaTable"
    // Première boucle : on teste le fichier
    TQ LitLigneCSV
       SI ResultatSQL[i] != LigneCSV
          FichierOK == False
       FIN SI
    FIN TQ
    // SI le fichier est OK, deuxième boucle : on fait l'update
    SI FichierOK
       TQ LitLigneCSV
          UpdateSQL(LigneCSV)
       FIN TQ
    SINON
       echo "Erreur dans le fichier !"
    FIN SI
    Citation Envoyé par bibi76 Voir le message
    Mais comme je l'avais dit tout à l'heure on peut pas mettre de else dans le while =/

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    i = 0
    TQ i < 10
       SI i < 5
          echo "<5"
       SINON
          echo ">=5"
       i=i+1
    FIN TQ
    Par contre, le return ne fonctionne que si tu es dans une fonction. Il sert à indiquer à la fonction quelle valeur renvoyer.

    Si tu veux creuser un peu (par exemple si tu as des problèmes de performance, ou si tu fais ça pour apprendre), tu peux largement optimiser le code en utilisant les fonctionnalités de ta BDD...

  11. #11
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2019
    Messages
    8
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2019
    Messages : 8
    Par défaut
    Hello !

    > Le mot important était d'abord

    Oui je faisais des tests, encore et encore la nuit dernière mais je galère un peu beaucoup avec les while et les if dans les while un vrai casse tête mais je commence à m'y faire

    > Tu as besoin de savoir si le fichier est "correct" avant de démarrer les updates.
    Il te faut donc deux étapes :
    1. Tu vérifies que le fichier est correct par rapport à ta table (avec une boucle WHILE).
    2. SI il est correct (je parle de tout le fichier) tu fais les updates (avec une seconde boucle WHILE).


    Merci pour ces précieux conseils ! C'est bon ça marche nickel (sauf mauvaise surprise) !! =D

    > Par contre, le return ne fonctionne que si tu es dans une fonction. Il sert à indiquer à la fonction quelle valeur renvoyer.
    Si tu veux creuser un peu (par exemple si tu as des problèmes de performance, ou si tu fais ça pour apprendre), tu peux largement optimiser le code en utilisant les fonctionnalités de ta BDD...


    Oui merci de la précision j'en prends note !
    Juste une dernière question par rapport à mon code :

    Code PHP : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
     //On teste le fichier si tout le fichier est correct
    					$entete = fgetcsv($fic,$taille,$delimiteur);
    					while(($champ = fgetcsv($fic,$taille,$delimiteur)) !== FALSE) {
    						$ref_nom = $champ[1];
    						echo $champ[1] . "<br/>";
    
    						//On vérifie si les résultats de la reqûete_2 correspondent bien aux résultats du libellés "nom" dans le fichier CSV.
    						if($tableau_nom_SQL[$i] !== $ref_nom){
    							echo "Attention votre fichier ne correspond pas a la table demandée ";
    							$fichierOK = false;
    							break;
    						}$i++;
    					} echo "Etape1";
    					fclose($fic);
    
    					$ficOK = fopen($chemin_fichier, 'r');
    					$tailleOK = 1024;
    					$delimiteurOK = ";";
    					if( $fichierOK ){
    						//$entete = fgetcsv($fic,$taille,$delimiteur);
    						while($champ = fgetcsv($ficOK,$tailleOK,$delimiteurOK)) {
    
    						//UPDATE
    
    						} echo "Etape2_OK";
    					}
    					else {
    						echo "Erreur dans le fichier ! ";
    					}
    					fclose($fic1);
    				}

    Je suis obligé d'ouvrir et fermer le fichier à 2 reprises ? Je testé l'ouverture et la fermeture du fichier en une fois mais ça ne semble pas marcher.
    Sinon merci encore pour le tuyau

  12. #12
    Membre éprouvé
    Profil pro
    Inscrit en
    Juin 2010
    Messages
    73
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2010
    Messages : 73
    Par défaut
    C'est une question de goût.

    En théorie, tu perds du temps à fermer/ouvrir un fichier, donc c'est mieux de le laisser ouvert.
    En pratique, je fais du code modulable, et j'aime bien avoir des blocs indépendants. Donc j'ouvre un fichier, je l'utilise et je le ferme, quitte à le faire plusieurs fois dans la même page.

    Si tu veux le laisser ouvert c'est possible. Il suffit de repositionner le pointeur en début de fichier : rewind(monfichier)

  13. #13
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2019
    Messages
    8
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2019
    Messages : 8
    Par défaut
    Ok ! Merci pour ton aide, ta disponibilité et le partage de ton savoir
    Sujet résolu

    Bonne journée !

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 5
    Dernier message: 27/08/2010, 07h29
  2. [phpMyAdmin] Importer un csv dans une table SQL
    Par Mohican69 dans le forum EDI, CMS, Outils, Scripts et API
    Réponses: 4
    Dernier message: 17/08/2010, 13h07
  3. exportation de d'un fichier csv vers une table sql
    Par sanounatibibt dans le forum VB.NET
    Réponses: 3
    Dernier message: 02/01/2010, 16h59
  4. Réponses: 4
    Dernier message: 05/09/2008, 11h03
  5. Réponses: 2
    Dernier message: 04/04/2008, 18h58

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo