2008-11-04 9 views
3

Je rencontre un problème lors de l'obtention d'une liste de champs à partir d'une requête définie lors de l'exécution par les utilisateurs de mon programme. Je laisse mes utilisateurs entrer une requête SQL dans un contrôle mémo et ensuite je veux les laisser passer par les champs qui reviendront et faire des choses telles que le format de la sortie, les valeurs de colonne de somme et ainsi de suite. Donc, je dois obtenir les noms des colonnes afin qu'ils aient un endroit pour entrer les informations supplémentaires.Obtention d'une liste de champs à partir d'un DBExpress TSQLQuery

Je ferais bien s'il n'y avait pas de paramètres, mais je dois aussi les laisser définir les paramètres de filtre pour la requête. Donc, si je veux mettre les paramètres à zéro, je dois savoir quel est le type de données du paramètre. J'utilise Delphi 2006. Je me connecte à une base de données Firebird 2.1 en utilisant le composant DBExpress TSQLConnection et TSQLQuery. Auparavant, j'ai réussi à utiliser:

pour i: = 0 à Qry.Params.Count - 1 do Qry.Params [i] .value: = varNull;

J'ai découvert que j'avais un problème lorsque j'ai essayé d'utiliser un paramètre de date. C'était juste une coïncidence que tous mes paramètres jusque-là avaient été des entiers (ID d'enregistrement). Il s'avère que varNull est simplement une constante énumérée avec une valeur de 1, donc j'obtenais des résultats acceptables (aucun enregistrement) fonctionnait bien.

J'ai seulement besoin d'une liste des champs. Peut-être que je devrais juste analyser la clause SELECT de l'instruction SQL. Je pensais mettre Qry.Prepared à True m'obtiendrait une liste des champs, mais pas une telle chance. Il veut des valeurs pour les paramètres.

Si vous avez une idée, je voudrais bien l'entendre. Merci pour toute aide.

Répondre

2

a de nouveau répondu « coz Je suis intéressé. Mes méthodes fonctionnent (avec mes requêtes) car elles ont été prédéfinies avec les types de données params préréglés au type correct :)

Je ne suis pas sûr comment vous attendez que la requête connaisse ou dérive le type de données du param étant donné que vous ne sélectionnez même pas le champ contre lequel il opère. Donc, je pense que la configuration de votre requête et la méthode de saisie de l'utilisateur nécessiteront plus d'attention. Je viens de voir comment j'ai fait ça il y a un moment. Je n'utilise pas une requête paramétrée - je viens d'obtenir les "valeurs de paramètres" de l'utilisateur et les place directement dans le SQL. Donc, votre sql se lirait alors:

SELECT s.hEmployee, e.sLastName
DE PR_Paystub de
INNER JOIN PR_Employee e = ON e.hKey s.hEmployee
OÙ s.dtPaydate> '01/01/2008 '

donc aucune connaissance de type de paramètre n'est nécessaire. Ne vous arrêtez pas à vos utilisateurs d'entrer des ordures, mais qui va revenir au contrôle d'entrée :)

1

Je ne suis pas sûr de la version de Delphi que vous utilisez. Dans l'aide Delphi 2006 sous Types de variantes, il est dit:

règles de conversion spéciales applicables au type de Borland.Delphi.System.TDateTime déclaré dans l'unité du système. Quand un Borland.Delphi.System.TDateTime est converti en tout autre type, il traité comme un double normal. Lorsqu'un entier, réel ou booléen est converti en un Borland.Delphi.System.TDateTime, il est d'abord converti en un double, puis lu comme une valeur date-heure. Lorsqu'une chaîne est convertie en un Borland.Delphi.System.TDateTime, il est interprété en tant que valeur date-heure en utilisant les paramètres régionaux. Lorsqu'une valeur Unassigned est converti en Borland.Delphi.System.TDateTime, il est traité comme la valeur réelle ou entière 0. La conversion d'une valeur nulle à Borland.Delphi.System.TDateTime soulève une exception.

La dernière phrase me semble importante. Je lirais que varNull ne peut pas être converti en TDateTime à mettre dans le champ, et donc vous obtenez l'exception que vous rencontrez.

Cela implique également que c'est le seul cas particulier.

Ne pourriez-vous faire quelque chose comme:

for i := 0 to Qry.Params.Count - 1 do 
begin 
    if VarType(Qry.Params[i].value) and varTypeMask = varDate then 
    begin 
    Qry.Params[i].value := Now; //or whatever you choose as your default 
    end 
    else 
    begin 
    Qry.Params[i].value := varNull; 
    end; 
end; 
2

Bien qu'un type de jeu de données légèrement différent ce que j'utilise avec TClientDataset simple et efficace :)

for i := 0 to FilterDataSet.Params.Count -1 do 
begin 
Case FilterDataSet.Params.Items[i].Datatype of 
    ftString: 
    ftSmallint, ftInteger, ftWord: 
    ftFloat, ftCurrency, ftBCD: 
    ftDate: 
    ftTime: 
    ftDateTime: 
    . 
    . 
    . 
end; 

fin;
ne pouvez-vous pas faire quelque chose de similaire avec la requête?

2

les gars que vous faites cette façon trop dur:

for i := 0 to Qry.Params.Count - 1 do begin 
    Qry.Params[i].Clear; 
    Qry.Params[i].Bound := True; 
end; 
0
TmpQuery.ParamByName('MyDateTimeParam').DataType := ftDate; 
TmpQuery.ParamByName('MyDateTimeParam').Clear; 
TmpQuery.ParamByName('MyDateTimeParam').Bound := True; 
0

Ce que je fini par faire était le suivant:

sNull := 'NULL'; 
Qry.SQL.Add(sSQL); 
for i := 0 to Qry.Params.Count - 1 do begin 
    sParamName := Qry.Params[i].Name; 
    sSQL := SearchAndReplace (sSQL, ':' + sParamName, sNull, DELIMITERS); 
end; 

je devais écrire SearchAndReplace mais c'était facile. Les délimiteurs sont juste les caractères qui signalent la fin d'un mot.

Questions connexes