Неправильный результат после нажатия кнопки Обновить в DBNavigator Delphi
-
18-09-2019 - |
Вопрос
Я столкнулся здесь с очень странной ситуацией.Я получаю доступ к базе данных (MDB) через JET.Я использую DBGrid и DBNavigator, чтобы разрешить пользователю доступ к нему.Набор данных создается с помощью компонента TADOQuery со следующим запросом:
SELECT *, (DateDiff ('y',[Birth Date], Now())) AS [Age] FROM TableName
Это работает нормально.Но всякий раз, когда я нажимаю кнопку Обновления в DBNavigator, результат этого вычисляемого поля становится неправильным.Например, если обычно у меня в столбце Возраст отображается 7, то после нажатия кнопки Обновить оно становится 40149, 7 изменяется на 40149, 6 изменяется на 40150, 0 на 40156 и т.д.Чтобы просмотреть правильный результат, мне нужно снова повторно открыть запрос.
Кто-нибудь может помочь?
Решение
Попробуйте следующее, которое вернет возраст в днях.
SELECT *, CINT(Now()-[Birth Date]) as AGE FROM TableName
Для возраста в годах используйте:
SELECT *, INT((Now()-[Birth Date]) / 365.242199) as AGEYRS from TableName
(обратите внимание, CINT округляет, INT - нет)
Причина, по которой это работает, заключается в том, что ACCESS сохраняет свою дату / время методом, аналогичным Delphi, в виде значения с плавающей точкой, где целая часть представляет собой количество дней, прошедших с определенного дня, а дробная часть - дробную часть этого дня ( 0.25 = 6 утра, 0.50 = полдень и т.д.).Таким образом, если вы хотите узнать разницу между двумя днями, просто возьмите разницу между номерами дней...что касается количества лет, разделите это на количество дней в году.
Редактировать
Другим вариантом здесь было бы создать вычисляемое поле в Delphi и выполнить логику там.В вашем onCalculated событии вы бы закодировали что-то вроде следующего:
procedure TForm1.ds1CalcFields(DataSet: TDataSet);
begin
DataSet.FieldByName('CALCDATE').AsInteger :=
Trunc((Date - DataSet.FieldByName('BIRTH DATE').AsDateTime) / 365.242199);
end;
Редактировать
И еще третий способ.Вместо того, чтобы разрешать обновлению работать так, как оно работает в данный момент, переопределите поведение и принудительно закройте / повторно откройте набор данных с помощью onClick навигатора:
procedure TForm1.dbnvgr1Click(Sender: TObject; Button: TNavigateBtn);
begin
if Button = nbRefresh then
begin
ds1.Close;
ds1.Open;
end;
end;
Другие советы
Попробуйте вместо этого использовать этот параметр интервала :
SELECT *, (DateDiff ('yyyy',[Birth Date], Now())) AS [Age] FROM TableName
Вот что означает "интервалы" :
yyyy Year
q Quarter
m Month
y Day of Year
d Day
w Weekday
ww Week
h Hour
n Minute
s Second
Я провел тест с вашим предыдущим комментарием, и у меня тоже такая же ошибка.
Я думаю, это ошибка где-то в навигаторе или в jet.
Когда вы нажмете обновить навигатор.показанный 40149 - это представление даты в виде двойного значения без вычисляемого материала.Похоже, что он использует только первый найденный столбец и отображает его.
Если вы попытаетесь преобразовать его в строку, отображаемые данные по-прежнему будут datetime.
Select *, ' ' & DateDiff(.......) as [Age] From table1;
Когда я использую столбец типа String или Number первым в вычисляемом поле, результат отображается так, как должен.Вы можете попробовать :
SELECT *, mid(id & (DateDiff ('y',[madate], Now())), len(id) + 1) AS [Age] FROM Table1
Или :
SELECT *, (id-id) + (DateDiff ('y',[madate], Now())) AS [Age] FROM Table1
Это довольно некрасиво, но это делает свое дело..