Probleme de requetes imbriquees [Résolu]

Vonscott 62 Messages postés vendredi 6 janvier 2006Date d'inscription 19 septembre 2011 Dernière intervention - 21 déc. 2007 à 11:33 - Dernière réponse : Vonscott 62 Messages postés vendredi 6 janvier 2006Date d'inscription 19 septembre 2011 Dernière intervention
- 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
Afficher la suite 

10 réponses

Répondre au sujet
neigedhiver 2492 Messages postés jeudi 30 novembre 2006Date d'inscription 14 janvier 2011 Dernière intervention - 22 déc. 2007 à 23:53
+3
Utile
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.
Cette réponse vous a-t-elle aidé ?  
Commenter la réponse de neigedhiver
cs_morpheus57 122 Messages postés vendredi 31 mars 2006Date d'inscription 30 décembre 2010 Dernière intervention - 21 déc. 2007 à 14:08
0
Utile
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
Commenter la réponse de cs_morpheus57
Vonscott 62 Messages postés vendredi 6 janvier 2006Date d'inscription 19 septembre 2011 Dernière intervention - 24 déc. 2007 à 11:47
0
Utile
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 
Commenter la réponse de Vonscott
neigedhiver 2492 Messages postés jeudi 30 novembre 2006Date d'inscription 14 janvier 2011 Dernière intervention - 24 déc. 2007 à 13:56
0
Utile
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.
Commenter la réponse de neigedhiver
Vonscott 62 Messages postés vendredi 6 janvier 2006Date d'inscription 19 septembre 2011 Dernière intervention - 24 déc. 2007 à 15:50
0
Utile
Re,

Voici le lien du copier/coller
Commenter la réponse de Vonscott
neigedhiver 2492 Messages postés jeudi 30 novembre 2006Date d'inscription 14 janvier 2011 Dernière intervention - 24 déc. 2007 à 18:09
0
Utile
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...
Commenter la réponse de neigedhiver
Vonscott 62 Messages postés vendredi 6 janvier 2006Date d'inscription 19 septembre 2011 Dernière intervention - 26 déc. 2007 à 17:50
0
Utile
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
Commenter la réponse de Vonscott
Vonscott 62 Messages postés vendredi 6 janvier 2006Date d'inscription 19 septembre 2011 Dernière intervention - 26 déc. 2007 à 18:04
0
Utile
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.
Commenter la réponse de Vonscott
neigedhiver 2492 Messages postés jeudi 30 novembre 2006Date d'inscription 14 janvier 2011 Dernière intervention - 26 déc. 2007 à 23:08
0
Utile
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 ;)
Commenter la réponse de neigedhiver
Vonscott 62 Messages postés vendredi 6 janvier 2006Date d'inscription 19 septembre 2011 Dernière intervention - 27 déc. 2007 à 11:34
0
Utile
Salut,

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

Bonnes vacances et bonnes fetes de fin d'année
Commenter la réponse de Vonscott

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.