Probleme de requetes imbriquees

Résolu
Vonscott Messages postés 61 Date d'inscription vendredi 6 janvier 2006 Statut Membre Dernière intervention 19 septembre 2011 - 21 déc. 2007 à 11:33
Vonscott Messages postés 61 Date d'inscription vendredi 6 janvier 2006 Statut Membre Dernière intervention 19 septembre 2011 - 27 déc. 2007 à 11:34
Salut à tous,


J'ai un script qui ressemble à cela :
<?php
$db = odbc_connect('base', '', '');
$query = "SELECT DISTINCT Article.IDArticle, Article.Photo,
Article.Designation, Article.ReferenceInterne, Article.Type,
Article.Concordance, Nomenclature.Quantite, Nomenclature.Repere FROM
Article, Nomenclature WHERE Nomenclature.IDArticle = Article.IDArticle
AND Nomenclature.IDProduit = '$_GET[appareil]' ORDER BY $myorder";
echo '';

$req = odbc_exec($db, $query) or die ('Erreur');
while($res = odbc_fetch_array($req))
 {
  echo
'----
...blahblah..., ';
  if($res['Concordance'] != '0')
   {
    $query_trv_maitre = \"SELECT IDArticle, Reference FROMArticle WHERE Concordance '$res[Concordance]' AND Maitre '1'\";
    $req_trv_maitre = odbc_do($db, $query_trv_maitre) or die ('Erreur');
    $res_trv_maitre = odbc_fetch_array($req_trv_maitre);
    echo
''.$res_trv_maitre[Reference].', ';
   }
  else
   {
    echo
''.$res_trv_maitre[Reference].', ';
   }
  echo
'';
 }
echo '
';
?>



Je n'ai jamais eu de probleme avec ce genre de requete avec mysql mais j'ai un probleme que je ne comprend pas avec odbc.

Dés que la condition if($res['Concordance'] <> '0') est
remplie, l'affichage change bien, il m'affiche bien
$res_trv_maitre[Reference] au lieu de $res[Reference] mais il sort de
la boucle while tout de suite apres meme si il reste des resultats.

Si je supprime la condition if, tous les resultats s'affichent bien.


Quelqu'un à une idée ????


PS : Base hyperfile, version 11 du driver odbc, php5, apache2.2

10 réponses

neigedhiver Messages postés 2480 Date d'inscription jeudi 30 novembre 2006 Statut Membre Dernière intervention 14 janvier 2011 19
22 déc. 2007 à 23:53
Salut,

@morpheus57 : il n'utilise peut-être pas mysqli ou pdo pour la bonne raison qu'il n'utilise pas une base mysql, mais une base hyperfile, moteur développé par PC Soft (éditeur de Windev). Il a pourtant pris la peine de le préciser.

@Vonscott : Je pense que tes requêtes ne sont pas optimisées. Certes, je ne sais pas pourquoi il sort de la boucle while à cause du if, mais je sais que tes requêtes sont mal écrites. En fait, il n'est pas censé sortir du while à cause d'une condition non vérifiée dans un bloc if. A moins que tu n'aies une version bugguée de PHP, ce comportement est à exclure : il s'agit donc probablement d'une erreur de ta part.
Deux choses : tu n'utilises pas de guillemets pour indexer ton tableau $res_trv_maitre. Il y fort à parier que $res_trv_maitre[Reference] provoque une erreur et que du coup, non seulement il sort de la boucle while, mais pire que tout, le script s'interrompt.
Pour le savoir :

error_reporting[E_ALL);

Idem pour $_GET[appareil] et $res[Concordance]
Si la variable $_GET['appareil'] est effectivement définie et qu'aucune erreur n'est affichée (ce qui est déconseillé en développement, ou bien c'est parce que tu travailles sur un site en production, ce qui est déconseillé également) c'est parce que par défaut, si la constante appareil (que php cherche quand ce n'est ni une chaine de caractères ni une variable) n'existe pas, il utilise le mot comme texte, mais en générant une erreur non fatale.

En regardant mieux tes 2 requêtes (la première puis celle que tu effectues sur CHAQUE enregistrement qui satisfait la condition), j'ai vu qu'elles tapent toutes les deux dans la table Article. C'est un vrai gaspi de performances. Ta deuxième requête ne fait que récupérer le champ "Reference" pour l'article en cours : tu gagnerais à le récupérer dans la première requête, même si tu ne t'en sers pas (à cause de la condition). Exécuter autant de requêtes est bien plus gourmand que le stockage d'un champ supplémentaire en mémoire.

Essaie ça :

$query "SELECT DISTINCT Article.IDArticle, Article.Photo, Article.Designation, Article.ReferenceInterne, Article.Reference, Article.Type, Article.Concordance, Nomenclature.Quantite, Nomenclature.Repere FROM Article, Nomenclature WHERE Nomenclature.IDArticle Article.IDArticle AND Nomenclature.IDProduit = '" . $_GET['appareil'] . "' ORDER BY $myorder";
echo '';
$req = odbc_exec($db, $query) or die ('Erreur');
while($res = odbc_fetch_array($req))
{
echo '----
...blahblah..., ';
if($res['Concordance'] != '0')
{
echo ''.$res['Reference'].', ';
}
else
{
echo ''.$res['Reference'].', ';
}
echo '';
}
echo '
';

Par pitié : fais une vérification sur $_GET['appareil'] avant de l'utiliser n'importe comment dans ta requête : c'est la porte ouverte à une magnifique attaque XSS. Il FAUT OBLIGATOIREMENT vérifier ce que tu mets dans ta requête SQL. Au minimum, un stripslashes(), mais le mieux est de faire un traitement poussé pour éviter de péter ta requête avec des caratères binaires.
3
cs_morpheus57 Messages postés 121 Date d'inscription vendredi 31 mars 2006 Statut Membre Dernière intervention 30 décembre 2010
21 déc. 2007 à 14:08
Bonjour,

Petite question toute simple : pourquoi tu n'utilise pas une librairie propre à mysql (mysqli) où même pdo ?
http://be.php.net/manual/fr/ref.mysqli.php
http://be.php.net/manual/fr/ref.pdo.php

http://www.mytravellingfriend.com/tf_morpheus
0
Vonscott Messages postés 61 Date d'inscription vendredi 6 janvier 2006 Statut Membre Dernière intervention 19 septembre 2011
24 déc. 2007 à 11:47
Salut neigedhiver,

Merci beaucoup de tes conseils, mais du coup d'autres question se posent.

1 - Excuse moi, une erreur s'est glissé dans le script que je donne ( c'est surement pour cela qu'il t'as semblé bizarre de faire deux requetes pour sortir le meme champ )
if($res['Concordance'] != '0')
 {  $query_trv_maitre "SELECT IDArticle, Reference FROM Article WHERE Concordance '$res[Concordance]' AND Maitre = '1'";
  $req_trv_maitre = odbc_do($db, $query_trv_maitre) or die ('Erreur');
  $res_trv_maitre = odbc_fetch_array($req_trv_maitre);
  echo '<td>'.$res_trv_maitre[Reference].'</td>';
 }
else
 {
  echo '<td>'.$res[ReferenceInterne].'</td>';
 }

En fait si l'article de la premiere boucle à une concordance, rechercher par le biais de la deuxieme requete l'article ayant la meme concordance et avec maitre a 1.
Existe t'il un moyen de le faire en une seule requete ??

2 - Je suis deja en error_reporting[E_ALL);
Aucune erreur ne s'affiche
Et le script sort de la boucle mais ne plante pas, j'ai bien une page valide, dans la source je retrouve bien </table></html>

3 - Pense tu vraiment que dans la requete '$_GET[appareil]' ou '" . $_GET['appareil'] . "' soit differents ?

4 - Rassure toi, le script donné est "light", je verifie effectivement le contenu de $_GET[appareil] qui est en fait un id
A ce sujet, pense tu qu'un simple is_numeric() soit suffisant 
0
neigedhiver Messages postés 2480 Date d'inscription jeudi 30 novembre 2006 Statut Membre Dernière intervention 14 janvier 2011 19
24 déc. 2007 à 13:56
Salut,

1. "En fait si l'article de la premiere boucle à une concordance, rechercher par le biais de la deuxieme requete l'article ayant la meme concordance et avec maitre a 1.
Existe t'il un moyen de le faire en une seule requete ??"

Certainement. Si tu tapes dans la même table les deux fois, il y a surement moyen d'économiser l'exécution de la deuxième requête (qui est d'ailleurs exécutée pour chaque article listée, si je comprends bien).
N'hésite pas à faire un copier/coller complet (en masquant juste les mots de passes et informations sensibles) : aider à corriger une erreur n'est pas possible sur une moitié de script, l'erreur pouvant être liée à un bout de code omis.
Il y a d'ailleurs un outils sur CS qui permet de faire un copier/coller de code avec colorisation (et que je n'ai jamais vu utilisé par quiconque ici) :
http://tools.codes-sources.com/copy-paste-code.aspx

Je te propose donc de faire un copier/coller complet, et de décrire également ta table (avec le code SQL pour la créer par exemple, que l'on obtient en exportant la table dans phpMyAdmin, ou avec la requête SHOW CREATE TABLE `ma_table`;)

Dis-moi également exactement ce que tu veux faire/obtenir : on verra alors le meilleur moyen de le faire.

2. C'est bizarre... Idem : montre le code entier

3. Oui, c'est vraiment différent. appareil, $appareil et 'appareil' sont 3 choses différentes.
Le premier est une constante, le second une variable, le troisième une chaine de caractères. Utilisé comme clé du tableau $_GET, le résultat est différent dans les 3 cas.

4. Oui, en toute logique, is_numeric devrait suffire. Tu peux aussi convertir en entier avec (int), ou récupérer la valeur entière avec int_val(). Il y a quelques petites différences de l'un à l'autre, qui impliquent un traitement différent pour assigner une valeur par défaut si besoin.
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
Vonscott Messages postés 61 Date d'inscription vendredi 6 janvier 2006 Statut Membre Dernière intervention 19 septembre 2011
24 déc. 2007 à 15:50
Re,

Voici le lien du copier/coller
0
neigedhiver Messages postés 2480 Date d'inscription jeudi 30 novembre 2006 Statut Membre Dernière intervention 14 janvier 2011 19
24 déc. 2007 à 18:09
J'avoue que j'ai un peu de mal à comprendre tes requêtes.
Tu fais une jointure sur la même table... Quel intérêt ? Je ne dis pas qu'il n'y en a pas, juste que je ne vois pas pourquoi...
Est-ce que tu peux m'expliquer ce que sont "concordance" et "maitre" ?
Que doit faire ta première requête, celle avec UNION ?
Et que doit faire la seconde, celle qui est exécutée autant de fois qu'il y a de concordance ?

J'arrive pas à me plonger dans ce que tu veux faire, je ne comprends pas encore ta logique, donc pas facile...

Cela dit, je ne vois rien qui justifie que le script sorte de la boucle while, si ce n'est le fait qu'il n'y ait plus d'enregistrement...
0
Vonscott Messages postés 61 Date d'inscription vendredi 6 janvier 2006 Statut Membre Dernière intervention 19 septembre 2011
26 déc. 2007 à 17:50
Salut,


Normal que tu n'ai pas compris la logique du script puisque je me suis trompé et que j'ai copier/coller un fichier test.


Je te redonne donc le lien du bon fichier








http://tools.codes-sources.com/copy-paste-code.aspx?ID=69



Excuse moi pour le derangement pour rien
0
Vonscott Messages postés 61 Date d'inscription vendredi 6 janvier 2006 Statut Membre Dernière intervention 19 septembre 2011
26 déc. 2007 à 18:04
En fait, le script sert a ceci

Je lui envoie un id d'appareil ($_GET[appareil])
la 1ere requete  recupere la liste des pieces contenues par l'appareil dans la table nomenclature (par le champ IDProduit). Chaques enregistrement retourné correspond à un article dont je recupere la reference et la designation, via la jointure pour l'affichage.

Si l'article à une concordance ( piece equivalente ) je relis la table article pour trouver toutes les pieces qui ont la meme concordance mais je selectionne seulement celle qui a Maitre ( booleen ) à 1

En gros si Concordance != 0 alors la piece peut etre remplacé par une autre reference  ( meme piece mais achetée chez un autre fournisseur )
Maitre == 1 veut dire que c'est cette piece que nous gerons en stock et celle qui sera fournie au client.
0
neigedhiver Messages postés 2480 Date d'inscription jeudi 30 novembre 2006 Statut Membre Dernière intervention 14 janvier 2011 19
26 déc. 2007 à 23:08
Salut,

Juste un message pour dire que je n'oublie pas ton problème, mais n'étant pas chez moi, je ne suis pas dans des conditions optimales pour reprendre ton code tout en assimilant tes explications : il faut que je m'immerge totalement, ce que je ne pourrai pas faire avant quelques jours...
Si t'es pas pressé à la minute, je tâcherai de m'y coller très prochainement (sans date précise...). Si t'es pressé, ben... si quelqu'un peut jeter un oeil...

Bonnes fêtes de fin d'année ;)
0
Vonscott Messages postés 61 Date d'inscription vendredi 6 janvier 2006 Statut Membre Dernière intervention 19 septembre 2011
27 déc. 2007 à 11:34
Salut,

Ne t'inquiete pas, pas de soucis, merci à toi de jetter un oeil

Bonnes vacances et bonnes fetes de fin d'année
0
Rejoignez-nous