2009-12-08 5 views
1

J'ai fait face à une situation très étrange ici. J'accède à la base de données (MDB) via JET. J'utilise DBGrid et DBNavigator pour permettre à l'utilisateur d'y accéder. Le jeu de données est créé à l'aide du composant TADOQuery, avec la requête suivante:Mauvais résultat après l'actualisation de DbNavigator Delphi

SELECT *, (DateDiff ('y',[Birth Date], Now())) AS [Age] FROM TableName 

Cela fonctionne correctement. Mais chaque fois que j'appuie sur le bouton Actualiser sur DBNavigator, le résultat de ce champ calculé devient erroné. Par exemple, si normalement j'ai 7 montré sur la colonne d'âge, après que j'appuie Refresh il devient 40149, 7 changements à 40149, 6 changements à 40150, 0 à 40156 etc. Afin d'afficher le résultat correct je dois rouvrir la question encore .

Quelqu'un peut-il aider?

Répondre

4

Effectuez les opérations suivantes, qui retournera l'âge en jours.

SELECT *, CINT(Now()-[Birth Date]) as AGE FROM TableName 

Pour l'âge en années d'utilisation:

SELECT *, INT((Now()-[Birth Date])/365.242199) as AGEYRS from TableName 

(note complète CINT, INT ne fonctionne pas)

La raison pour laquelle cela fonctionne est que l'accès stocke la date/heure dans un méthode similaire à Delphi, comme un flottant où la partie entière est le nombre de jours depuis un jour spécifique et la partie fractionnaire comme partie fractionnaire de ce jour (0,25 = 6 heures, 0,50 = midi, etc.). Ainsi, si vous voulez connaître les différences entre deux jours, il suffit de prendre les différences entre les nombres de jours ... pour le nombre d'années, divisez-le par le nombre de jours dans une année.

EDIT

Une autre option ici serait de créer un champ calculé à Delphes et y effectuer la logique.Dans votre cas onCalculated vous code quelque chose comme ce qui suit:

procedure TForm1.ds1CalcFields(DataSet: TDataSet); 
begin 
    DataSet.FieldByName('CALCDATE').AsInteger := 
    Trunc((Date - DataSet.FieldByName('BIRTH DATE').AsDateTime)/365.242199); 
end; 

EDIT

Et une troisième méthode. Plutôt que de permettre l'actualisation de travailler comme il le fait actuellement, remplacer le comportement et forcer une fermeture/réouverture de l'ensemble de données en utilisant le onClick du navigateur:

procedure TForm1.dbnvgr1Click(Sender: TObject; Button: TNavigateBtn); 
begin 
    if Button = nbRefresh then 
    begin 
     ds1.Close; 
     ds1.Open; 
    end; 
end; 
+0

C'est ce que je première pensée et j'ai essayé cela. Ça n'a pas marché. Lancer et erreur ADO lorsque vous utilisez CINT lorsque vous actualisez avec dbnavigator. Et la fonction INT ne fait rien parce que 40149 est un INT ... – Pmax

+1

Seulement parce que la date a été entrée sans un temps. La structure interne est toujours un flottant, donc l'int est nécessaire. J'ai édité ma réponse et ajouté une autre manière en utilisant un champ calculé Delphi qui fonctionne correctement. – skamradt

1

Essayez ce paramètre intervalle à la place:

SELECT *, (DateDiff ('yyyy',[Birth Date], Now())) AS [Age] FROM TableName 

Voici ce que « intervalles » signifie:

yyyy Year 
q Quarter 
m Month 
y Day of Year 
d Day 
w Weekday 
ww Week 
h Hour 
n Minute 
s Second 
+0

je dois calculer l'âge jours –

1

Je l'ai fait un test avec votre commentaire précédent, et j'ai aussi la même erreur.

Je pense que c'est un bug quelque part dans le navigateur ou dans le jet.

Lorsque vous cliquez sur rafraîchir sur le nav. le 40149 montré est la représentation de la date comme un double sans les trucs calculés. Il semble n'utiliser que la première colonne trouvée et l'afficher.

Si vous essayez de le transformer en chaîne, les données affichées sont toujours datetime. Lorsque j'utilise une colonne de type Chaîne ou Nombre d'abord dans le champ calculé, le résultat est affiché comme il se doit. Vous pouvez essayer:

SELECT *, mid(id & (DateDiff ('y',[madate], Now())), len(id) + 1) AS [Age] FROM Table1 

Ou:

SELECT *, (id-id) + (DateDiff ('y',[madate], Now())) AS [Age] FROM Table1 

Ceci est assez laid, mais il fait le tour ..