Delphi 2009 Firebird 2.1 problème type de données TIME

Résolu
informatixo Messages postés 129 Date d'inscription mercredi 4 février 2004 Statut Membre Dernière intervention 25 juillet 2012 - 4 nov. 2010 à 19:06
cs_cantador Messages postés 4720 Date d'inscription dimanche 26 février 2006 Statut Modérateur Dernière intervention 31 juillet 2021 - 15 nov. 2010 à 12:23
Bonsoir le forum,

J'ai voulu essayer Firebird car tout le monde en parle et cela me semble une solution opensource très intéressante mais j'ai un problème sur un ajout de donnée.

J'utilise Delphi 2009 Professionnel avec Firebird 2.1 et les composants ADO via le driver ODBC proposé lors de l'installation de Firebrd. Je me sers d'Easy+ pour administrer la base de données.

Après avoir configuré correctement l'alias ODBC j'ai créé une table Pointages(identifiant (clé primaire en INTEGER), annee (INTEGER), semaine(INTEGER), jour (DATE), heure (TIME)).

Je me suis servi d'un ADOQuery paramétré avec le code suivant :
    sqlRequete.Close;
    sqlRequete.SQL.Clear;
    sqlRequete.SQL.Add('INSERT INTO Pointages VALUES(:identifiant, :annee, :semaine, :jour, :heure)');
    sqlRequete.Parameters.ParamByName('identifiant').Value := intDernierIdentifiant + 1;
    sqlRequete.Parameters.ParamByName('annee').Value := YearOf(dtMaintenant);
    sqlRequete.Parameters.ParamByName('semaine').Value := WeekOf(dtMaintenant);
    sqlRequete.Parameters.ParamByName('jour').Value := FormatDateTime('yyyy-mm-dd', dtMaintenant);
    sqlRequete.Parameters.ParamByName('heure').Value := FormatDateTime('hh:nn:ss', dtMaintenant);
    sqlRequete.ExecSQL;


Le message d'erreur est le suivant "L'erreur suivante s'est produite : [ODBC Firebird Driver]Restricted data type attribute violation".

Après analyse du problème, je me suis rendu compte qu'il portait sur le type de données TIME (en d'autre termes sur heure) et plus précisement l'utilisation du paramètre pour lui affecter une valeur car quand je procède comme ci-dessous cela fonctionne :
    sqlRequete.Close;
    sqlRequete.SQL.Clear;
    sqlRequete.SQL.Add('INSERT INTO Pointages VALUES(:identifiant, :annee, :semaine, :jour, ''15:12:15'')');//, :heure)');
    sqlRequete.Parameters.ParamByName('identifiant').Value := intDernierIdentifiant + 1;
    sqlRequete.Parameters.ParamByName('annee').Value := YearOf(dtMaintenant);
    sqlRequete.Parameters.ParamByName('semaine').Value := WeekOf(dtMaintenant);
    sqlRequete.Parameters.ParamByName('jour').Value := FormatDateTime('yyyy-mm-dd', dtMaintenant);
//    sqlRequete.Parameters.ParamByName('heure').Value := FormatDateTime('hh:nn:ss', dtMaintenant);
    sqlRequete.ExecSQL;


Le problème vient donc bien du paramètre ! J'ai vérifié dans la documentation de Firebird et pour spécifier TIME c'est bien 'HH:MM:SS'.

J'ai fais plusieurs autres tentatives sans le FormatDateTime() avec uniquement la chaine textuelle représentant l'heure ou bien en utilisant QuotedStr() mais sans succès.

Quelqu'un pourrait-il me venir en aide car je m'y casse les dents depuis un petit moment et je suis un peu à court d'idée.

Merci par avance pour votre aide.

Que la force soit avec vous !

16 réponses

informatixo Messages postés 129 Date d'inscription mercredi 4 février 2004 Statut Membre Dernière intervention 25 juillet 2012 1
10 nov. 2010 à 19:41
Bonsoir le forum,

[quote=yanb]sqlRequete.Parameters.ParamByName('Jour').Value := DateTimeToTimeStamp(dtMaintenant);/quote

Désolé yanb mais .Value est un Variant et DateTimeToTimeStamp renvoi un TTimeStamp donc à la compilation ça bloque.

J'ai pour ma part fait un peu de veille technologique sur les composants du lien que j'ai communiqué un peu plus haut et j'ai rapidement trouvé que les composants UIB étaient très adaptés et gratuits.

J'ai donc choisi d'utiliser ces composants. Ils ont l'avantage d'être rapides et d'accès direct à la base de données Firebird (pas besoin d'ODBC) et peuvent être reliés à un TDataSource et donc utilisés avec un TDBGrid, etc.

J'ai remis dans ma table le champs "Jour" en type de données "DATE" et j'ai rajouté un champs "DateHeure" en type de données "TIMESTAMP".

Voici le code d'une requête paramétrée qui fonctionne avec ces composants :
    UIBQuery1.Close;
    UIBQuery1.SQL.Clear;
    UIBQuery1.SQL.Add('INSERT INTO Pointages VALUES(:identifiant, :annee, :semaine, :jour, :heure, :dateheure)');
    UIBQuery1.Params.ByNameAsInteger['identifiant'] := intDernierIdentifiant + 1;
    UIBQuery1.Params.ByNameAsInteger['annee'] := YearOf(dtMaintenant);
    UIBQuery1.Params.ByNameAsInteger['semaine'] := WeekOf(dtMaintenant);
    UIBQuery1.Params.ByNameAsDate['jour'] := Round(dtMaintenant);
    UIBQuery1.Params.ByNameAsDateTime['heure'] := dtMaintenant;
    UIBQuery1.Params.ByNameAsDateTime['dateheure'] := dtMaintenant;
    UIBQuery1.ExecSQL;


Même si je n'ai pas réussi à régler mon problème initial en utilisant ADO + ODBC j'ai néanmoins réussi à trouver une solution alternative très intéressante donc je vais mettre ce post en "Résolu" comme ceci si quelqu'un rencontre le même problème il saura qu'il existe deux solutions :
[list]
Passer la requête en dur au lieu d'utiliser les paramètres comme me l'a suggéré yanb
Ou utiliser les composants UIB pour arriver au même résultat en conservant les paramètres.
/list

Je vous remercie tous pour votre aide et pour vos axes de réflexion.

A plus au détour d'un autre post.

Que la force soit avec vous !
3
Cirec Messages postés 3833 Date d'inscription vendredi 23 juillet 2004 Statut Modérateur Dernière intervention 18 septembre 2022 50
5 nov. 2010 à 09:52
Salut,

ton erreur ne serait elle pas du au fait que tu aies confondu "HH:MM:SS" avec "HH:NN:SS" ?
// sqlRequete.Parameters.ParamByName('heure').Value := FormatDateTime('hh:nn:ss', dtMaintenant);



[hr]@+Cirec
[hr]
0
cs_yanb Messages postés 271 Date d'inscription lundi 27 octobre 2003 Statut Membre Dernière intervention 7 juillet 2022 14
5 nov. 2010 à 10:38
Salut,
essaye avec :
sqlRequete.Parameters.ParamByName('jour').Value := '{ d ' +QuotedStr(FormatDateTime('yyyy-mm-dd',dtMaintenant))+'}';
sqlRequete.Parameters.ParamByName('heure').Value := '{ t ' +QuotedStr(FormatDateTime('hh:nn:ss',dtMaintenant))+'}'
@+ yanb
0
cs_cantador Messages postés 4720 Date d'inscription dimanche 26 février 2006 Statut Modérateur Dernière intervention 31 juillet 2021 13
5 nov. 2010 à 11:32
bonjour,

'hh:nn:ss'
ou
'hh:mm:ss'

on trouve les deux dans la doc..

cantador
0

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

Posez votre question
cs_yanb Messages postés 271 Date d'inscription lundi 27 octobre 2003 Statut Membre Dernière intervention 7 juillet 2022 14
5 nov. 2010 à 12:22
Salut,
effectivement hh:mm:ss = hh:nn:ss
mais attention
en fait si dans le format h est avant m alors m devient n
si dans le format pas h avant m alors m reste m => qui est mois
Exemple de resultats différents:
ShowMessage(FormatDateTime('hh:mm:ss',Now));
ShowMessage(FormatDateTime('hh:nn:ss',Now));
ShowMessage(FormatDateTime('mm:hh:ss',Now));
ShowMessage(FormatDateTime('nn:hh:ss',Now));

@+yanb
0
informatixo Messages postés 129 Date d'inscription mercredi 4 février 2004 Statut Membre Dernière intervention 25 juillet 2012 1
5 nov. 2010 à 21:47
Bonsoir à tous,

Tout d'abord merci beaucoup à tous pour votre aide.

Effectivement comme tout le monde l'a précisé nn spécifie les minutes.

yanb j'avais moi aussi essayé le code trouvé sur développez concernant la gestion du DateTime pour ODBC mais sans succès. Voici le lien original qui précise les formats pour ceux qui veulent y jeter un coup d'oeil. Au cas où je me sois trompé j'ai quand même réessayez en utilisant ton code par copier-coller et j'ai le même message d'erreur à savoir :

L'erreur suivante s'est produite : L'application utilise une valeur d'un type incorrect pour l'opération en cours

Le paramètre n'a pas l'air de vouloir prendre ce type de valeur.

Hélas, je n'ai rien trouvé de neuf de mon côté. Hier j'ai essayé de plancher sur une chaine qui puisse gérer la double quote mais là aussi le paramètre n'a pas l'air de vouloir me le prendre !

Je m'en remet donc une fois de plus à vous au cas où quelqu'un ai une autre piste à explorer.

De mon côté je vais faire des tests sur TIMESTAMP pour voir comment le paramètre le gère et je vous tiendrais au courant.

Une fois de plus merci à tous et à plus.

Que la force soit avec vous !
0
informatixo Messages postés 129 Date d'inscription mercredi 4 février 2004 Statut Membre Dernière intervention 25 juillet 2012 1
6 nov. 2010 à 00:54
Re bonsoir le forum,

Bon je viens de faire quelques tests supplémentaires en changeant le type de données du champ "jour" de DATE vers TIMESTAMP et en écartant pour le moment le champ TIME en lui saisissant en dur l'heure sans utiliser de paramètre.

Déjà ça marche ! J'ai utilisé 'yyyy-mm-dd hh:nn:ss' mais grosse surprise quand je regarde avec IBEasy+ le contenu de la table pour le champ concerné j'ai la date mais pas date + heure comme je devrais m'attendre à trouver. Pour en avoir le coeur net j'ai fais un export du contenu de la table dans un fichier Excel et je l'ai aussi fais afficher dans un dbgrid mais j'obtiens uniquement la date et non date + heure.

Est-ce les composants ADO qui ne gèrent pas correctement le driver ODBC de Firebird ou bien est-ce la version 2.1 de Firebird (je viens de voir qu'il en sont maintenant à la 2.5) ?

En espérant une idée de genie,

Que la force soit avec vous ! (force est de constater qu'elle n'est pas avec moi pour le moment ! Peut-être une Firebird vergence) --> IODA : paddawan peut-être que je redevienne il vaudrait mieux !
0
cs_yanb Messages postés 271 Date d'inscription lundi 27 octobre 2003 Statut Membre Dernière intervention 7 juillet 2022 14
6 nov. 2010 à 10:52
Salut,
pour le lien désolé mais moi c'est Lien
La question que je me pose à tu vraiment dans ton champ "jour" des données TimeStamp, ne sont-elles pas toujours en Date.
Peut-être les composant ADO le Problème...
Pour le moment pas d'autres idées.
@+yanb
0
informatixo Messages postés 129 Date d'inscription mercredi 4 février 2004 Statut Membre Dernière intervention 25 juillet 2012 1
6 nov. 2010 à 11:36
Bonjour à tous,

Autant pour moi yanb pour le lien.

Alors j'ai fais d'autres tests pour en avoir le coeur net ! Le champ est bien en TIMESTAMP car j'ai ouvert la console SQL d'IBEasy+ et j'ai tenté une insertion et là ça marche parfaitement (date + time). C'est à n'y rien comprendre !

Je commence à douter du driver ODBC ou alors est-ce les composants ADO ?

Je vais essayer de passer à Firebird 2.5 pour voir dans un premier temps sinon il faudra peut-être que j'envisage de passer à d'autres composants qu'ADO pour attaquer la base mais là j'aimerais avoir un retour d'expérience pour me conseiller de bons composants.

Je taffe ce weekend alors j'essaierais le changement de base dimanche soir et je vous tiendrais au courant.

Je vous remercie par avance pour les conseils que vous pourrez m'apporter ou de nouvelles pistes.

Merci à tous et bon weekend !

Que la force soit avec vous !
0
Cirec Messages postés 3833 Date d'inscription vendredi 23 juillet 2004 Statut Modérateur Dernière intervention 18 septembre 2022 50
6 nov. 2010 à 18:13
au temps pour moi .. je ne savais pas que nn == mm


[hr]@+Cirec
[hr]
0
cs_yanb Messages postés 271 Date d'inscription lundi 27 octobre 2003 Statut Membre Dernière intervention 7 juillet 2022 14
7 nov. 2010 à 11:38
Salut,
@Cirec : nn == mm (pas toujours) j'ai eu le problème une fois donc maintenant je le sais, mais
j'utilise toujours mm
Sinon peut-être une piste, TimeStamp est-il bien utilisé en variant avec les composants ADO ?
Si tu essayés en passant par des TDateTime et asDateTime...
Exemple :
sqlRequete.Parameters.ParamByName('Jour').asDateTime := DateTimeToStr(dtMaintenant);
ou
sqlRequete.Parameters.ParamByName('Jour').asDateTime := FormatDateTime('yyyy-mm-dd', dtMaintenant);
Pourquoi cette idée,tout simplement si tu l'écris en dur apparemment ca marche.
Peut-être des conversions TimeStamp et TDateTime différente en variant
Ou tout simplement la requête SQL en dur.
sqlRequete.SQL.Add('INSERT INTO Pointages (identifiant,annee,semaine,jour,heure) VALUES (QuotedStr(IntToStr(intDernierIdentifiant + 1)),QuotedStr(IntToStr(YearOf(dtMaintenant))),
QuotedStr(IntToStr(WeekOf(dtMaintenant))),QuotedStr(FormatDateTime('yyyy-mm-dd', dtMaintenant)) ,QuotedStr(FormatDateTime('hh:nn:ss', dtMaintenant)))');
voilà les idées du jour
@+Yanb
0
informatixo Messages postés 129 Date d'inscription mercredi 4 février 2004 Statut Membre Dernière intervention 25 juillet 2012 1
7 nov. 2010 à 20:44
Bonsoir le forum,

Merci pour ces efforts !

@Cirec > il n'y a pas de mal ! Voici l'extrait de la documentation pour "mm" --> "Affiche le numéro du mois en le préfixant d'un zéro (01 à 12). Si le spécificateur mm suit immédiatement un spécificateur h ou hh, il provoque l'affichage des minutes plutôt que du numéro du mois." Donc mm affiche minute uniquement après h ou hh sinon c'est des mois.

@yanb > merci beaucoup de t'acharner pour me venir en aide. Cependant, sauf erreur de ma part ce qui est largement possible, le ".asquelquechose (.asDateTime, .asInteger, etc.)" n'est disponible qu'avec un FieldByName (ou du moins un élément représentant un champ) et non un paramètre.

Effectivement, il me reste la solution de la requête en dur mais je préfère tout de même la requête paramétrée qui me semble plus propre et plus pratique.

En ce qui concerne le reste, voici les tests que j'ai pu réaliser :
[list]Je suis passé en Firebird 2.5 et cela n'a rien changé !/list
[list]J'ai retélécharger le driver ODBC en prenant soin de bien prendre le dernier et je pense que le problème viens de là !/list
Voici une image de la page de configuration de l'alias ODBC

J'ai essayé tous les changements possible et rien n'y fait ! Je pense que les composants ADO n'arrive pas à fonctionner correctement avec ce driver ODBC.

Avez-vous connaissance d'autres composants pour remédier à ce problème ? Je sais qu'avec Delphi XE il y a un driver natif pour DBExpress pour gérer Firebird mais hélas je suis en 2009.

Merci à tous.

Que la force soit avec vous !
0
cs_yanb Messages postés 271 Date d'inscription lundi 27 octobre 2003 Statut Membre Dernière intervention 7 juillet 2022 14
8 nov. 2010 à 09:19
Salut,
Exact AsDateTime avec FieldByName,
mais j'essayerais bien la requête SQL en dur,sur les dates pour voir le résultat.
Pourquoi utiliser un formatage string (FormatDateTime) alors que tu utilises un variant.
sqlRequete.Parameters.ParamByName('Jour').Value := dtMaintenant;
Je croix que le problème viens de là, tu lui envois un string alors qu'il attend un DateTime.
Pour le formatage de la date passer par ShortDateFormat et ShortTimeFormat dans ce cas.
Si tu essayes en dur c'est différent tu lui envois du string et c'est l'ODBC ou FireBird qui s'occupe de convertir le string dans le format attendu si je ne me trompe.
Donc dans ma logique tu ne dois pas convertir le format avec value (variant).
Peut-être que je me trompe mais c'est une piste...
@+Yanb
0
informatixo Messages postés 129 Date d'inscription mercredi 4 février 2004 Statut Membre Dernière intervention 25 juillet 2012 1
9 nov. 2010 à 01:25
Bonsoir le forum,

Merci beaucoup yanb pour ton implication !

[quote=yanb]sqlRequete.Parameters.ParamByName('Jour').Value := dtMaintenant;/quote

Je l'ai essayé mais ça ne fonctionne pas et m'affiche le même message d'erreur que plus haut à savoir :


L'erreur suivante s'est produite : [ODBC Firebird Driver]Restricted data type attribute violation.

[quote=yanb]Pourquoi utiliser un formatage string (FormatDateTime) alors que tu utilises un variant./quote

Parce qu'en passant dtMaintenant directement j'ai (date + time) alors qu'en spécifiant un formatage en string je peux lui envoyer que l'heure. De plus c'est de cette façon que je procédais avec le moteur Microsoft Jet 4.0 quand j'utilisais Access.

[quote=yanb]Pour le formatage de la date passer par ShortDateFormat et ShortTimeFormat dans ce cas./quote

Les deux fonctions renvoient elles aussi un string et semblent être identiques à FormatDateTime.

J'ai fais un un essai avec VarFromDateTime qui n'a pas été concluant non plus !

[quote=yanb]mais j'essayerais bien la requête SQL en dur,sur les dates pour voir le résultat./quote

Je l'ai essayé pour toi et je peux te confirmer que ça fonctionne mais avec le code suivant :

    sqlRequete.SQL.Add('INSERT INTO Pointages VALUES (' + IntToStr(intDernierIdentifiant + 1) + ',' + IntToStr(YearOf(dtMaintenant)) + ',' + IntToStr(WeekOf(dtMaintenant)) + ',' + QuotedStr(FormatDateTime('yyyy-mm-dd', dtMaintenant)) + ',' + QuotedStr(FormatDateTime('hh:nn:ss', dtMaintenant)) + ')');


Mais comme je te l'ai précisé je préfère utiliser des requêtes paramétrées. J'ai trouvé le lien suivant qui montre un sondage pour des composants Delphi permettant de manipuler FireBird. Apparemment ils permettent un accès direct plutôt que de passer par la couche ODBC (ADO + ODBC). Demain si j'ai le temps je ferais quelques essais et je vous tiendrais au courant des tests.

Merci infiniment pour l'aide et si vous avez d'autres pistes ou des retours d'expérience sur les composants du lien n'hésitez pas.

Merci encore et à plus !

Que la force soit avec vous !
0
cs_yanb Messages postés 271 Date d'inscription lundi 27 octobre 2003 Statut Membre Dernière intervention 7 juillet 2022 14
9 nov. 2010 à 09:39
Salut,
Erreur de ma part c'est comme ca :
sqlRequete.Parameters.ParamByName('Jour').Value := DateTimeToTimeStamp(dtMaintenant);
Donc en passant en dur la conversion ce fait d'elle même alors quand passant par les paramètres
c'est à toi d'envoyer le bon format.
Il existe aussi TimeStampToDateTime.
@+yanb
0
cs_cantador Messages postés 4720 Date d'inscription dimanche 26 février 2006 Statut Modérateur Dernière intervention 31 juillet 2021 13
15 nov. 2010 à 12:23
bonjour,

Ils ont l'avantage d'être rapides et d'accès direct à la base de données Firebird (pas besoin d'ODBC)

oui, tout à fait :

UIB, IBO, FIB+, tous très bons..

cantador
0
Rejoignez-nous