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 :

Requête ne ramenant pas le résultat escompté


Sujet :

PHP & Base de données

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éprouvé
    Homme Profil pro
    Inscrit en
    Mai 2004
    Messages
    803
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Mai 2004
    Messages : 803
    Par défaut Requête ne ramenant pas le résultat escompté
    Bonjour,

    J'ai déjà exposé mon problème dans le forum "MySql", mais je ne suis pas certain que le problème que je rencontre ne provienne pas de Php.

    Dans une application pour call center, je traite une série de "suivis" qui, lors de leur traitement, permettent une composition automatique du numéro de téléphone.

    Afin que deux employés du call center ne traitent pas en même temps un même suivi, dans ma table "suivis", j'ai un champ "occupe" qui est à 1 lorqu'il est en cours de traitement, sinon à 0.

    Donc, dans mes requêtes de sélection du suivi à traiter au moment dit par l'employé, je ne sélectionne qu'un suivi dont le champ "occupe" est à 0. Voici, ci-après, une de mes requêtes :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    select cibles.* from cibles, suivis where refCampagne = " . $param[0] . " and cibles.id = refCible and !cloture and rappelPrior = 1 and (dateRappel > date_sub(curdate(), interval 1 day) and dateRappel < date_sub(now(), interval 15 minute)) and !occupe order by dateRappel desc limit 1
    Le problème est qu'en production, il arrive que des employés travaillent en même temps sur le même suivi, alors que mon champ "occupe" est bien updaté à 1 dès qu'un employé travaille dessus. Ce qui m'étonne d'autant plus, c'est que lorsque je fais le test via PhpMyAdmin, ma requête ne me ramène pas les suivis occupés, tandis que, via l'application, en ouvrant deux instances de FireFox, je reproduis à chaque fois le phénomène.

    Voici deux informations supplémentaires. Dans ma requête, j'ai utilisé "SQL_NO_CACHE", mais cela n'a rien changé. Deuxièmement, j'utilise, pour tous les utilisateurs de l'application, une seule connection persistante à la base de données.

    Voici les différentes portions de codes utiles :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    $retour = $objCampagne->chargerCible($tabVendPrior);
    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
    public function chargerCible($tabVendeurs)
       {
        if(get_magic_quotes_gpc()) //test si les magic_quotes sont activées
         $objUtilisateur = unserialize(stripslashes($_COOKIE['utilisateur']));
        else
         $objUtilisateur = unserialize($_COOKIE['utilisateur']);
     
        $tab[0] = $this->id;
        $tab[1] = $objUtilisateur->getId();
     
        if(!empty($tabVendeurs))
         $tab = array_merge($tab, $tabVendeurs);
     
        $transaction = CtransactionsBdd::GetInstance("MYSQL", "speedcall");
        $resuReq = $transaction->select("MYSQL_chargerCibleLapsTempsEnCoursPrior", $tab); // On charge une cible dont la date de rappel indiquée par l'utilisateur se situe dans le laps de temps +- 15 minutes par rapport à l'heure actuelle
     
        if ($transaction->getErreur() == "Aucun résultat")
         {
          $resuReq2 = $transaction->select("MYSQL_chargerCibleRappelDateJourPrior", $tab); // On charge une cible dont la date de rappel indiquée par l'utilisateur est celle du jour
     
          if(!count($resuReq2[0]))
    ...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    case "MYSQL_chargerCibleRappelDateJourPrior":
             return "select SQL_NO_CACHE cibles.* from cibles, suivis where refCampagne = " . $param[0] . " and cibles.id = refCible and !cloture and rappelPrior = 1 and (dateRappel > date_sub(curdate(), interval 1 day) and dateRappel < date_sub(now(), interval 15 minute)) and !occupe order by dateRappel desc limit 1";
            break;
    Une dernière chose très étonante, afin de tracer au mieux les requêtes exécutées, j'ai voulu les écrire dans un fichier texte via ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    case "MYSQL_chargerCibleRappelDateJourPrior":
            $Fnm = "../rappReq.txt";
            $inF = fopen($Fnm,"w");
            $texte = "select SQL_NO_CACHE cibles.* from cibles, suivis where refCampagne = " . $param[0] . " and cibles.id = refCible and !cloture and rappelPrior = 1 and (dateRappel > date_sub(curdate(), interval 1 day) and dateRappel < date_sub(now(), interval 15 minute)) and !occupe order by dateRappel desc limit 1"; 
            fwrite($inF,$texte."\n");
            fclose($inF);
            return "select SQL_NO_CACHE cibles.* from cibles, suivis where refCampagne = " . $param[0] . " and cibles.id = refCible and !cloture and rappelPrior = 1 and (dateRappel > date_sub(curdate(), interval 1 day) and dateRappel < date_sub(now(), interval 15 minute)) and !occupe order by dateRappel desc limit 1";
            break;
    Lors de la première exécution, je retrouve bien la requête dans le fichier texte. Par contre je n'y retrouve aucune trace d'une autre requête, alors que les deux mêmes fiches client sont affichées à l'écran.

    Quelqu'un aurait une idée?

    Merci d'avance pour toute piste que vous pourriez m'indiquer.

  2. #2
    Membre Expert
    Avatar de gene69
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    1 769
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Janvier 2006
    Messages : 1 769
    Par défaut
    le SQL_NO_CACHE était effectivement inutile.

    Si j'ai bien compris tu as un drapeau pour dire qu'une ligne (correspondant à un traitement) était en cours de traitement . Et que tu te retrouves avec deux personnes qui prennent le même drapeau en même temps. Et ça dans un FPS ou dans un SGBD c'est mal vu.

    sans avoir regardé ton code ni la discutions dans le forum mysql, je vais te dire c'est un cas improbable d'une lecture concurrente et la mise à jour en fonction de la lecture qui ne se fait pas de façon atomique.

    Tu dois d'une façon ou d'une autre avoir un bout de code qui dit

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Selection du traitement ou drapeau = baissé
    Mise a jour traitement, drapeau = levé quand il s'agit du traitement X.
    Il faudrait que tu testes le affected_row() de la mise à jour, renvoyer une exception si c'est différent de 1.

    Je va lire ton code. Tu utilises un framework connu?

  3. #3
    Membre Expert
    Avatar de gene69
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    1 769
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Janvier 2006
    Messages : 1 769
    Par défaut
    en fait pour etre plus exlicite du point de vue sql, j'ai oublié une condition:

    UPDATE traitement SET drapeau = "levé" WHERE drapeau = "baissé" AND traitement = "X"

  4. #4
    Membre Expert
    Avatar de gene69
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    1 769
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Janvier 2006
    Messages : 1 769
    Par défaut
    Pour ce qui est de l'abscence de log, à mon avis ce serait plus simple si tu avais une possibilité de loguer tout ce qui va à travers mysql_query() ou sont équivalent nativement dans la classe de surcouche et pas dans un bout de code qui ne donne pas l'impression d'y être.

    En plus avec un peu d'astuce tu peux tres bien remonter dans la pile debug_backtrace() pour retrouver le fichier et la fonction qui lance l'appel à select(), execute().. ma surcouche perso est assez naïve pour que ce soit simple puisque je n'ai qu'une méthode query() à surveiller. C'est pour ça que je pose la question du framework.

  5. #5
    Membre éprouvé
    Homme Profil pro
    Inscrit en
    Mai 2004
    Messages
    803
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Mai 2004
    Messages : 803
    Par défaut
    Bonsoir et merci beaucoup de l'attention que tu portes à mon problème. Je patauge grave depuis plusieurs jours...

    Concernant l'editeur, j'utilise PhpEdit.

    Ensuite, voici la portion de code dans laquelle je flague le suivi comme étant en cours de traitement :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    $retour = $objCampagne->chargerCible($tabVendPrior); //Là, je charge une cible dont le suivi n'a pas son champ "occupe" à 1
     
    if(is_array($retour))
     {
      $objCible = new CCible($retour);
     
      if(!isset($_SESSION['campagne'])) //Pour le premier appel effectué à partir de listeCampagnes.inc
       $_SESSION['campagne'] = serialize($objCampagne);
     
      $_SESSION['cible'] = serialize($objCible);
     
      $objSuivi = $objCampagne->chargerSuivi($retour['id']);
      $objSuivi->setOccupe(1); // Ici, je flague mon suivi comme étant occupé
    Voici le code de ma méthode setOccupe() :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    public function setOccupe($occupe)
       {
        $this->occupe = $occupe;
        $tab['id'] = $this->id;
        $tab['occupe'] = $occupe;
        $transaction = CtransactionsBdd::GetInstance("MYSQL", "speedcall");
        $resuReq = $transaction->update("MYSQL_suiviOccupe", $tab);
       }
    Concernant le !cloture, c'est simplement pour savoir si le traitement du suivi est terminé ou si il doit y avoir encore des traitements ultérieurs. Le problème ne vient pas du champ cloture, mais du champ occupe.

    J'ai essayé la synthaxe , mais cela n'a rien changé.

  6. #6
    Membre Expert
    Avatar de gene69
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    1 769
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Janvier 2006
    Messages : 1 769
    Par défaut
    Citation Envoyé par dubitoph Voir le message
    Concernant l'editeur, j'utilise PhpEdit.
    framework != editeur de texte.

    soit t'es distrait, soit t'es stagiaire.

    Ca se confirme: Teste ta valeur de retours de la mise à jour, lance une exception si c'est anormal et enleve les !cloture comme te le conseille avec justesse RunCodePhp, d'abord parce que si par hasard ça marche c'est pas l'usage d'utiliser cette syntaxe.

  7. #7
    Membre Expert Avatar de RunCodePhp
    Profil pro
    Inscrit en
    Janvier 2010
    Messages
    2 962
    Détails du profil
    Informations personnelles :
    Localisation : Réunion

    Informations forums :
    Inscription : Janvier 2010
    Messages : 2 962
    Par défaut
    Je vois aussi que tu utilise des transactions (CtransactionsBdd), qu'un update est effectué, mais je ne vois pas de commit ?
    C'est normal ? (c'est effectué dans la fonction ?)
    Est ce réellement une transaction d'ailleurs ?

  8. #8
    Membre éprouvé
    Homme Profil pro
    Inscrit en
    Mai 2004
    Messages
    803
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Mai 2004
    Messages : 803
    Par défaut
    Je n'utilise pas de framework, j'utilise en connaissance de cause un éditeur.

    Quand à mon champ clôturé, il ne pose pas de problème, c'est bien le champ occupe qui apparemment l'est (le champs cloture ne fait rien que m'indiquer qu'il n'y aura plus de traitement à effectuer pour ce suivi).

    Par contre, j'ai testé directement la mise à jour de mon champ occupé de la façon suivante : j'ai exécuté mon code (donc effectué un appel), puis, avant de terminer le traitement de celui-ci, j'ai vérifié, via une requête dans PhpMyAdmin que mon champ occupe avait bien pris la valeur 1, ce qui était le cas.

    Ce qui m'étonne, c'est que si je lance à ce moment la requête de sélection d'une cible (et suivi) dans PhpMyAdmin, il ne me sélectionne pas (de manière correcte), le suivi occupé. Par contre, si je le fais via une autre session dans mon application, là il me ramène (de façon erronée) le suivi occupé

  9. #9
    Membre Expert Avatar de RunCodePhp
    Profil pro
    Inscrit en
    Janvier 2010
    Messages
    2 962
    Détails du profil
    Informations personnelles :
    Localisation : Réunion

    Informations forums :
    Inscription : Janvier 2010
    Messages : 2 962
    Par défaut
    Salut

    Je suis très très loin d'avoir tout vu en SQL, mais ce qui me saute yeux c'est ceci : !cloture, et à plusieurs reprise.
    Comme le dysfonction à l'air lié à ce champ, je me dis qu'il faudrait confirmer certains points.

    En 1er, cette syntaxe m'est inconnue en SQL, j'aurais plus vu quelque chose comme : AND cloture = 1 ou cloture > 0

    Mais comme ça à l'air de ne pas générer d'erreur SQL (encore que faudrait peut être vérifier les logs), donc en admettant que c'est une syntaxe valide ...
    Est ce que cette négation tient compte d'une valeur de 0 ou 1 ?
    Ou ça ne serait pas plutôt NULL (ou éventuellement rien/inéxistant) ? Dans ce dernier ça, 0 ou 1 n'étant pas NULL, c'est comme si c'était VRAI (ce qui justifierait peut être le dysfonctionnement).

    Mais je fabule peut être, c'est une idée.


    Petite parenthèse en passant, et à titre perso.
    Je privilégierais plutôt des jointures naturelles comme JOIN, INNER JOIN
    que de simple égalités comme : cibles.id = refCible actuellement.

Discussions similaires

  1. Ma requête ne me donne pas le résultat escompté
    Par Invité dans le forum Langage SQL
    Réponses: 4
    Dernier message: 23/06/2014, 14h50
  2. Requête ne ramenant pas le résultat voulu
    Par artotal dans le forum Requêtes
    Réponses: 3
    Dernier message: 14/07/2012, 10h58
  3. [MySQL] Requête ne donne pas de résultat
    Par elepetit dans le forum PHP & Base de données
    Réponses: 3
    Dernier message: 07/07/2010, 12h07
  4. [GNUPlot] Multiplot qui ne donne pas le résultat escompté
    Par Nicocot dans le forum Autres langages
    Réponses: 0
    Dernier message: 24/11/2008, 20h05
  5. Requête imbriquée, ou pas, avec résultat nul
    Par skyl_pioup dans le forum Requêtes
    Réponses: 3
    Dernier message: 01/12/2007, 20h50

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