Delphi 2009 Firebird 2.1 problème type de données TIME [Résolu]

Messages postés
133
Date d'inscription
mercredi 4 février 2004
Dernière intervention
25 juillet 2012
- 4 nov. 2010 à 19:06 - Dernière réponse :
Messages postés
4996
Date d'inscription
dimanche 26 février 2006
Dernière intervention
27 mars 2018
- 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 !
Afficher la suite 

Votre réponse

16 réponses

Meilleure réponse
Messages postés
133
Date d'inscription
mercredi 4 février 2004
Dernière intervention
25 juillet 2012
10 nov. 2010 à 19:41
3
Merci
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 !

Merci informatixo 3

Avec quelques mots c'est encore mieux Ajouter un commentaire

Codes Sources a aidé 92 internautes ce mois-ci

Commenter la réponse de informatixo
Messages postés
4229
Date d'inscription
vendredi 23 juillet 2004
Dernière intervention
3 août 2018
5 nov. 2010 à 09:52
0
Merci
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]
Commenter la réponse de Cirec
Messages postés
260
Date d'inscription
lundi 27 octobre 2003
Dernière intervention
4 mars 2016
5 nov. 2010 à 10:38
0
Merci
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
Commenter la réponse de cs_yanb
Messages postés
4996
Date d'inscription
dimanche 26 février 2006
Dernière intervention
27 mars 2018
5 nov. 2010 à 11:32
0
Merci
bonjour,

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

on trouve les deux dans la doc..

cantador
Commenter la réponse de cs_cantador
Messages postés
260
Date d'inscription
lundi 27 octobre 2003
Dernière intervention
4 mars 2016
5 nov. 2010 à 12:22
0
Merci
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
Commenter la réponse de cs_yanb
Messages postés
133
Date d'inscription
mercredi 4 février 2004
Dernière intervention
25 juillet 2012
5 nov. 2010 à 21:47
0
Merci
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 !
Commenter la réponse de informatixo
Messages postés
133
Date d'inscription
mercredi 4 février 2004
Dernière intervention
25 juillet 2012
6 nov. 2010 à 00:54
0
Merci
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 !
Commenter la réponse de informatixo
Messages postés
260
Date d'inscription
lundi 27 octobre 2003
Dernière intervention
4 mars 2016
6 nov. 2010 à 10:52
0
Merci
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
Commenter la réponse de cs_yanb
Messages postés
133
Date d'inscription
mercredi 4 février 2004
Dernière intervention
25 juillet 2012
6 nov. 2010 à 11:36
0
Merci
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 !
Commenter la réponse de informatixo
Messages postés
4229
Date d'inscription
vendredi 23 juillet 2004
Dernière intervention
3 août 2018
6 nov. 2010 à 18:13
0
Merci
au temps pour moi .. je ne savais pas que nn == mm


[hr]@+Cirec
[hr]
Commenter la réponse de Cirec
Messages postés
260
Date d'inscription
lundi 27 octobre 2003
Dernière intervention
4 mars 2016
7 nov. 2010 à 11:38
0
Merci
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
Commenter la réponse de cs_yanb
Messages postés
133
Date d'inscription
mercredi 4 février 2004
Dernière intervention
25 juillet 2012
7 nov. 2010 à 20:44
0
Merci
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 !
Commenter la réponse de informatixo
Messages postés
260
Date d'inscription
lundi 27 octobre 2003
Dernière intervention
4 mars 2016
8 nov. 2010 à 09:19
0
Merci
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
Commenter la réponse de cs_yanb
Messages postés
133
Date d'inscription
mercredi 4 février 2004
Dernière intervention
25 juillet 2012
9 nov. 2010 à 01:25
0
Merci
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 !
Commenter la réponse de informatixo
Messages postés
260
Date d'inscription
lundi 27 octobre 2003
Dernière intervention
4 mars 2016
9 nov. 2010 à 09:39
0
Merci
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
Commenter la réponse de cs_yanb
Messages postés
4996
Date d'inscription
dimanche 26 février 2006
Dernière intervention
27 mars 2018
15 nov. 2010 à 12:23
0
Merci
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
Commenter la réponse de cs_cantador

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.