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

Langage Perl Discussion :

[perl] sql > table hash multidimensionnel


Sujet :

Langage Perl

  1. #1
    Membre à l'essai
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    18
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2006
    Messages : 18
    Points : 12
    Points
    12
    Par défaut [perl] sql > table hash multidimensionnel
    bonjour tous,
    j'avais été bien aidé pour le début de mon script, je reviens pour la fin.
    je récupère une liste de liens dans une base mysql, je teste leur existence et je mets les faux dans un tableau par site (1 site peut avoir plusieurs liens).
    ensuite j'envoie un mail à chaque site avec la liste de SES liens faux.
    mon problème : ça liste TOUS les liens de TOUS les sites à chaque fois.

    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
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
     
    # prendre tous les liens
    $query = "SELECT * FROM liens";
    $sth = $dbh->prepare($query);
    $sth->execute;
     
    # enregistrer les url fausses
    my %site_list = {};
    while ($data = $sth->fetchrow_hashref()) {
        $nb_liens++;
        # test url
        $etat = &check_url($data->{'url'});
        if ($etat eq "ok"){
            $nb_ok++;
        } else {
            my %h = {};
            #on index chaque url par nom
            $h->{$data->{'lien_nom'}} = $data->{'url'};
            #on index par site
            $site_list->{$data->{'site_id'}} = $h;    
            $nb_bad_liens++;
        }
    }
    my $list_l;
    for my $id (keys %{$site_list}) {
        # infos site
        $query = "SELECT site_nom FROM sites WHERE site_id = '$id' LIMIT 1";
        $sth = $dbh->prepare($query);
        $sth->execute;
        $data_site = $sth->fetchrow_hashref();
        $site_nom = $data_site->{'site_nom'};
     
        # infos webmestre
        $query = "SELECT * FROM webmestres WHERE site_id = '$id' LIMIT 1";
        $sth = $dbh->prepare($query);
        $sth->execute;
        $data_wbm = $sth->fetchrow_hashref();
        $wbm_nom =     $data_wbm->{'wbm_nom'};
        $wbm_prenom = $data_wbm->{'wbm_prenom'};
        $wbm_email = $data_wbm->{'wbm_email'};
     
        # liste des liens
        $list_l = '';
        for my $name (keys %{$site_list->{$id}}){
            $list_l .= "'$name' - " . $site_list->{$id}->{$name} . "\n";    
        }
     
        # envoyer l'email
        $msg= <<_EOM_;
    Bonjour $wbm_prenom $wbm_nom,
    Vous êtes webmestre du site "$site_nom" inscrit sur l'annuaire.
    Un ou plusieurs liens enregistrés dans l'annuaire pour votre site semblent inaccessibles :
    $list_l
     
    ####### etc... (et envoi)
    merci du coup de main

  2. #2
    Membre à l'essai
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    18
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2006
    Messages : 18
    Points : 12
    Points
    12
    Par défaut allo ? à l'aide !
    je crois que mon problème viens de la manière de lister les liens là :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    for my $name (keys %{$site_list->{$id}}){
    	$list_l .= "'$name' - " . $site_list->{$id}->{$name} . "\n";    
    }
    en appelant avec %{$site_list->{$id}} j'espère lister uniquement les "name" inclus dans le sous-tableau "id", créé comme ceci à chaque ligne:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    $h->{$data->{'lien_nom'}} = $data->{'url'};
    $site_list->{$data->{'site_id'}} = $h;
    mais ça me liste le tableau complet.
    alors quelle est la solution, appeler avec des trucs du genre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    while (($key,$val) = each %HIST) {
            $list_l = ...
        }
    ou bien tester la valeur de id à chaque itération ? (et comment ?

    merci d'un petit coup de main, ça paraît pas compliqué mais je suis débutant en perl

  3. #3
    Expert éminent
    Avatar de Jedai
    Homme Profil pro
    Enseignant
    Inscrit en
    Avril 2003
    Messages
    6 245
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Avril 2003
    Messages : 6 245
    Points : 8 586
    Points
    8 586
    Par défaut
    Je ne sais pas quel est le problème réel, mais il y a plein de petites erreurs dans ce script.

    Il s'agit soit d'une erreur de copier-coller, soit d'une erreur plus grave (tu n'utilises pas le pragma strict, et pour un programme comme le tien c'est une très mauvaise idée) :
    En effet, cette ligne devrait être :
    sinon tu aurais à la fois un warning, et une erreur quand tu utiliserais $site_list->{} par la suite, si tu as bien les pragmas "warnings" et "strict" activées.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
            my %h = {};
            #on index chaque url par nom
            $h->{$data->{'lien_nom'}} = $data->{'url'};
            #on index par site
            $site_list->{$data->{'site_id'}} = $h;    
            $nb_bad_liens++;
    Avec ce code tu n'auras jamais plus d'un lien enregistré par site, car tu recrées à chaque fois le hashref que tu mets dans $site_list->{$data->{'site_id'}}...


    Par ailleurs la fin de ton script a l'air correct, tu n'as pas besoin (probablement) de la corriger. As-tu essayé de faire exécuter ce script dans le débogueur pour voir quelles valeurs tes variables prennent ?

    EDIT : Ok j'ai trouvé... Tu as effectivement un problème, c'est là :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
            my %h = {};
            #on index chaque url par nom
            $h->{$data->{'lien_nom'}} = $data->{'url'};
    Visiblement d'après ta description du problème, tu as effectivement négligé d'utiliser "strict", ce qui t'aurais immédiatement mis sur la voie, en effet contrairement à ce que j'ai affirmé la première fois, tu ne recrées pas le hashref à chaque fois, tu ne le recrées JAMAIS ! Autrement dit il y a une seule hashref pour l'ensemble des sites, ce qui correspond bien au fait que tous les liens sont mélangés dans ta sortie (et confirme probablement que la seconde partie de ton script est correcte).
    L'erreur est la même que la première pointé :
    Ici tu voulais dire :
    Et dans ce cas tu aurais effectivement obtenu le comportement, erroné par ailleurs, que j'ai décris en premier par erreur (un lien par site).

    Ce que tu dois faire, c'est simplement remplacer :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
            my %h = {};
            #on index chaque url par nom
            $h->{$data->{'lien_nom'}} = $data->{'url'};
            #on index par site
            $site_list->{$data->{'site_id'}} = $h;    
            $nb_bad_liens++;
    par :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
            $site_list->{$data->{'site_id'}}{$data->{'lien_nom'}} = $data->{'url'};    
            $nb_bad_liens++;
    Par ailleurs :
    Rajoute "use strict;" en haut de ton script !!!!!!!
    Cette mésaventure ne te serais jamais arrivé si tu l'avais fait.

    --
    Jedaï

  4. #4
    Membre à l'essai
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    18
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2006
    Messages : 18
    Points : 12
    Points
    12
    Par défaut ah !
    quelqu'un qui se penche sur mon problème et le fait efficacement

    alors effectivement, j'ai copier-collé des réponses que j'avais eu précédemment sur des forums concernant ce problème. Notamment
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
            my %h = {};
            #on index chaque url par nom
            $h->{$data->{'lien_nom'}} = $data->{'url'};
            #on index par site
            $site_list->{$data->{'site_id'}} = $h;
    J'ai l'habitude de la simplicité des tableaux PHP et la complexité de la gestion en Perl me perd un peu (beaucoup). en autodidacte, j'arrive pas encore à bien saisir certaines subtilités du perl !

    Dans mon script, je lance dès le début un processus fils qui envoie les emails et le processus père envoie une phrase au navigateur avant d'être tué dès le début. Je ne vois donc pas les erreurs du script.

    Si ta solution me fait passer de 3 lignes à 1 en plus, ça me fait plaisir

    je testerai dès rentré chez moi
    merci.

  5. #5
    Membre à l'essai
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    18
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2006
    Messages : 18
    Points : 12
    Points
    12
    Par défaut youpi
    super, ça marche donc avec le remplacement proposé, génial !

    mais j'aimerai bien comprendre pourquoi on peut utiliser $ et qu'il n'y a pas de % dans ta ligne de code. C'est bien des hachages ... ?

  6. #6
    Expert éminent
    Avatar de Jedai
    Homme Profil pro
    Enseignant
    Inscrit en
    Avril 2003
    Messages
    6 245
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Avril 2003
    Messages : 6 245
    Points : 8 586
    Points
    8 586
    Par défaut
    Citation Envoyé par pierrickg
    super, ça marche donc avec le remplacement proposé, génial !

    mais j'aimerai bien comprendre pourquoi on peut utiliser $ et qu'il n'y a pas de % dans ta ligne de code. C'est bien des hachages ... ?
    Non, ce ne sont pas des hachages, mais des références sur des hachages. {} est une référence sur un hash anonyme, vide, c'est un scalaire.
    En fait :
    c'est équivalent à :
    Autrement dit :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    my %h = "HASH(0x2265d0)" => '';
    (le chiffre varie bien sûr).

    Si tu avais utilisé "warnings" et que tu avais exécuté le script, ce que tu devrais toujours faire (en fait un bon IDE pour Perl te permettrait de le faire en un raccourci), tu aurais eu l'avertissement :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Reference found where even-sized list expected at ...
    Ce qui t'aurait mis sur la voie au moins !
    Sans parler de ce que mettre "strict" t'aurait dit, même seulement en compilant le script (avec l'option -c), même sans l'exécuter. As-tu mis "strict" maintenant ?

    Donc je reprend : %h est un hachage, tu lui affecte un scalaire (une référence sur un hachage), ce qui est déjà une erreur, mais ensuite tu ne l'utilise jamais :
    Comme la flèche le montre, ici on a une référence sur un hachage, $h, si on accédait au hachage %h, on écrirait :
    (Le $ ici est parce que le résultat de cette expression est un scalaire, si tu avais mis @, ç'aurait été une tranche de hachage et tu aurais pu mettre une liste de string entre les {}, si tu avais mis % ç'aurait été une erreur).

    En bref, @h, $h et %h sont trois variables différentes ne partageant aucun caractères communs, et ici tu déclarais %h et travaillait avec $h. Avec "use strict;" tu t'en serais rendu compte tout de suite, mais je suppose que tu n'as pas prêté trop attention aux avertissements et conseils que tu trouves un peu partout sur ce forum ?

    --
    Jedaï

  7. #7
    Membre à l'essai
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    18
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2006
    Messages : 18
    Points : 12
    Points
    12
    Par défaut
    je n'ai pas lu tous les postes sur les définitoins de variables et les gestions de tableau sur le forum, désolé !

    Il faut simplement que je potasse "programming perl" d'O'Reilly qu'on m'a prêté ce WE pour connaître toutes les subtilités et les différences entre les mêmes notations en PHP qui ne veulent pas dire la même chose !

    j'ai ajouté "use strict" mais en lançant le script ça m'a envoyé sur la page d'erreur du serveur, au lieu de m'indiquer les erreurs du script.
    je l'ai donc enlevé en attendant, ça marche bien mais il me faudra + de rigeur

    merci bcp

  8. #8
    Expert éminent
    Avatar de Jedai
    Homme Profil pro
    Enseignant
    Inscrit en
    Avril 2003
    Messages
    6 245
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Avril 2003
    Messages : 6 245
    Points : 8 586
    Points
    8 586
    Par défaut
    Citation Envoyé par pierrickg
    j'ai ajouté "use strict" mais en lançant le script ça m'a envoyé sur la page d'erreur du serveur, au lieu de m'indiquer les erreurs du script.
    je l'ai donc enlevé en attendant, ça marche bien mais il me faudra + de rigeur
    Si tu t'es retrouvé sur le serveur, c'est qu'il y a encore des erreurs dans ton script, retirer use strict pour les masquer n'est pas une solution !!
    Je t'ai expliqué comment trouver ces erreurs (au moins appeler perl -c sur ton script une fois).

    --
    Jedaï

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

Discussions similaires

  1. commande SQL truncate table xxx
    Par Yogy dans le forum SQL
    Réponses: 1
    Dernier message: 07/10/2004, 14h57
  2. [PL/SQL] Utilisation table PL/SQL dans clause IN
    Par Yorglaa dans le forum PL/SQL
    Réponses: 13
    Dernier message: 05/10/2004, 10h36
  3. requete sql mutlis tables
    Par tommath dans le forum Langage SQL
    Réponses: 12
    Dernier message: 30/08/2004, 09h54
  4. Réponses: 8
    Dernier message: 13/08/2004, 12h32
  5. [SQL SERVER] Table contient trop d'enregistrements ?
    Par Tankian dans le forum MS SQL Server
    Réponses: 10
    Dernier message: 10/08/2004, 10h40

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