Bonjour,
J'essaye de faire une requéte imbriqué preparé en PHP avec PDO sur SQLSERVER mais je n'y arrive pas.
Voilà ce que je fais :
$dossier = 111;
$sql = "select ndoss
from GROUPES
where id_examen = (select MAX(id_examen) as id_examen
from GROUPES
where ndoss = :dossier)";
$prepare = $this->db->prepare($sql);
$prepare->bindParam(":dossier", $dossier, PDO::PARAM_INT);
$prepare->execute(array($dossier));
$resultat = $prepare->fetchAll(PDO::FETCH_OBJ);
return $resultat;
Ce code doit me remonter le numero d'examen (max) par rapport à un numéro de dossier et ensuite me remonter tous les dossiers affectés à ce numéro d'examen.
(Via un numéro de dossier je remonte son dernier examen et donc tous les dossier affécté à cet examen.)
Si je mets en dur la variable ndoss = $dossier ça marche mais si je veux le faire proprement en requete preparé avec :dossier et bindParam ça marche pas.
Voilà mon erreur : SQLSTATE[22018]: Invalid character value for cast specification: 206 [Microsoft][ODBC Driver 11 for SQL Server][SQL Server]Conflit de types d'op�randes�: text est incompatible avec int (SQLExecute[206] at ext\pdo_odbc\odbc_stmt.c:254)
Si je fais que cette requete seul :
select MAX(id_examen) as id_examen
from GROUPES
where ndoss = :dossier
Là ça marche, c'est dés lors que je passe en requete imbriqué que ça plante.
Voilà je demande votre aide pour faire au mieu.
Merci par avance.
Si je fait une requete avec "union" c'est pareil le fait d'avoir un variable ne fonctionne pas.
Sans "union" ça marche.
Salut Huggy le type de ndoss dans la BDD est INT mais la variable $dossier est en string car retour formulaire.
var_dump ($dossier) = string(5) "61732";
Cependant même si je mets $dossier = intval($dossier) avant ça ne marche pas.
var_dump ($dossier) = string(5) "61732"
$dossier = int_val($dossier);
var_dump ($dossier) = int(61732)
Et dans ce cas là pourquoi si je fait une requete simple du type :
select MAX(id_examen) as id_examen
from GROUPES
where ndoss = :dossier
Là ça marche alors c'est pour ça que je ne comprend pas !
Dés qu'il y a une sous requete, union et peut-être autre chose ça ne marche plus.
merci de regarder en tout cas.
Est-ce logique de renommer MAX(id_examen) en id_examen ?
il y a conflit, que vaut id_examen ensuite ? le max ou le champ ?
C'est débile, mais pourquoi tu ne fais pas un "ORDER BY id_examen DESC LIMIT 1" ?
pour avoir ceci :
select ndoss
from GROUPES
where ndoss = :dossier
order by id_examen DESC
limit 1
J'ai pas testé, mais ça devrait faire le même résultat
@huggy : Si j’enlève le "AS id_examen" ça change rien c'est juste pour renommer le champ .
@Kareylo : Pour le "order..." c'est pas le problème à mes yeux.
Le problème pour moi c'est d'avoir une variable dans une requête imbriqué.
Quand c'est une requête imbriqué avec une variable string qui pointe sur un champ (varchar) il suffit que je l'entour de ' pour que ça marche.
Ce que je ne trouve pas normal.
exemple :
$sql = " select MAX(id_examen) as id_examen
from GROUPES
where ndoss = :dossier" ; // si ndoss est un varchar requête simple pas besoin des ' pour que ça marche
$sql = " select ndoss
from GROUPES
where id_examen = (select MAX(id_examen) as id_examen
from GROUPES
where ndoss = ':dossier')"; // si ndoss est un varchar il me faut les ' dans une requête imbriqué pour que ça marche
$sql = "select ndoss
from GROUPES
where id_examen = (select MAX(id_examen) as id_examen
from GROUPES
where ndoss = ':dossier')"; // si ndoss est un INT ça ne marche pas
$sql = "select ndoss
from GROUPES
where id_examen = (select MAX(id_examen) as id_examen
from GROUPES
where ndoss = :dossier)"; // si ndoss est un INT ça ne marche pas
$sql = "select MAX(id_examen) as id_examen
from GROUPES
where ndoss = :dossier // si ndoss est un INT dans une requête simple ça marche
$sql = "select ndoss
from GROUPES
where id_examen = (select MAX(id_examen) as id_examen
from GROUPES
where ndoss = CONVERT(varchar,:dossier))"; // si ndoss est un INT ça marche ce qui me parait incohérent.
Je ne trouve aucune logique à tout ceci.
Petit rappel j'appelle SQL Server (odbc:Driver={ODBC Driver 11 for SQL Server}).
@Kareylo le probléme c'est que pour un id_examen tu peux avoir plusieurs ndoss d'ou la requete imbriqué.
Sur StackOverflow il y a un article qui ressemble à ton pb
J'ai pas testé mais en faisant un cast ça pourrait marcher
CAST(CAST(:dossier AS varchar) AS INTEGER)
Bonjour.
Si j’enlève le "AS id_examen" ça change rien c'est juste pour renommer le champ .
Vu le code que tu nous montres, ce n'est pas logique ce que tu fais, pourquoi renommer un champ avec le nom qu'il a déjà ?
C'est comme-ci quelqu'un te disait par exemple : "Tu t'appelle Vincent, à compter d'aujourd'hui, tu t'appelleras Vincent ?
Tu vois un changement toi ?
Ensuite, il faut que tu m'expliques quelque chose.
Pourquoi est-ce que tu définis deux fois le nom de la table dans une même requête qui ne contient aucune jointures de tables ?
Pour le "order..." c'est pas le problème à mes yeux.
Sauf que ça simplifierait la tâche au niveau SQL et éviterait une baisse de performance inutile.
Si tu penses comme-ça, qu'est-ce que ça va être quand tu vas continuer de cette manière pour des requêtes avec des jointures profondes/complexes.
Bonjour,
@Lartak merci de m'avoir renommer ainsi je préfére :)
Sans blague, j'ai essayé beaucoup de chose et je n'avais pas le AS au debut.
NIveau performance pour toi un order by limit 1 est plus performant qu'un select max, bon à savoir mais sous sql server sur 700 000 ligne ça va aussi vite.
SInon on tourne autour de mon probléme car le order .... je peux pas le faire car je peux avoir plusieurs numero de dossier par id d'examen.
Comme j'ai pu le dire precedement en faisant ça dans ma requête imbriqué ça marche :
.... where ndoss = CONVERT(varchar,:dossier))
OU
.... where ndoss = CONVERT(varchar,?))
Cependant je trouve étrange que ça marche en changeant le type de la variable en varchar alors que ndoss attend un INT.
Le ORDER va faire un tri de la totalité des enregistrements, ça peut être long
le MAX va directement chercher la plus grande valeur dans l'index (s'il existe)
CAST(CAST(? AS varchar) AS INTEGER)
avec
$prepare->execute(array($dossier));
Ca fonctionne mais pas ça :
CAST(CAST(:dossier AS varchar) AS INTEGER)
$prepare->bindParam(':dossier', $dossier, PDO::PARAM_INT);
Je ne comprend pas tout mais bon on va continuer ainsi !!