Delphi Firebird 时间戳字段的 DBGrid 日期格式

Delphi DBGrid date format for Firebird timestamp field

我将 Firebird 数据库的内容显示到 TDBgrid 中。数据库有一个 'TIMESTAMP' 数据类型字段,我想以 date/time 格式显示: 'YYYY/MM/DD HH:mm:ss'。 (现在显示为'YYMMDD HHmmss')

如何实现?

我试过这个:

procedure TDataModule1.IBQuery1AfterOpen(DataSet: TDataSet);
begin
  TDateTimeField(IBQuery1.FieldByName('timestamp_')).DisplayFormat := 'YYYY/MM/DD HH:mm:ss';
end;

但这会在程序的其他部分造成一些副作用,因此它不是替代方案。例如,在 'IBQuery1.Open' 语句中,我在清除数据库的方法中收到“...timestamp_ not found...”调试器消息。

function TfrmLogger.db_events_clearall: integer;
begin
  result := -1;
  try
    with datamodule1.IBQuery1 do begin
      Close;
      With SQL do begin
        Clear;     
        Add('DELETE FROM MEVENTS')
      end;
      if not Prepared then 
        Prepare;      
      Open;          //Exception here          
      Close;
      Result := 1;
    end;
  except
    on E: Exception do begin
      ShowMessage(E.ClassName);
      ShowMessage(E.Message);          
      Datamodule1.IBQuery1.close;
    end;
  end;
end;

我在尝试打开写入数据库的查询时收到相同的异常消息。

*编辑 >>

我把数据库修改清楚如下:

function TfrmLogger.db_events_clearall: integer;
var
  IBQuery: TIBQuery;
  IBTransaction: TIBTransaction;
  DataSource: TDataSource;
begin
  result := -1;

  //Implicit local db objects creation
  IBQuery := TIBQuery.Create(nil);
  IBQuery.Database := datamodule1.IBdbCLEVENTS;

  DataSource := TDataSource.Create(nil);
  DataSource.DataSet := IBQuery; 

  IBTransaction := TIBTransaction.Create(nil);
  IBTransaction.DefaultDatabase := datamodule1.IBdbCLEVENTS;
  IBQuery.Transaction := IBTransaction;

  try
    with IBQuery do begin
      SQL.Text := DELETE FROM MSTEVENTS;
      ExecSQL;
      IBTransaction.Commit;
      result := 1;
    end;
  except
    on E : Exception do
    begin
      ShowMessage(E.ClassName + ^M^J + E.Message);
      IBTransaction.Rollback;
    end;
  end;

  freeandnil(IBQuery);
  freeandnil(DataSource);
  freeandnil(IBTransaction);
end;

清除数据库后,我可以将记录加载到 dbgrid 中,好像数据库还没有更新。程序重启后可以看到所有记录都被删除了

整个function TfrmLogger.db_events_clearall好像很可疑

  1. 您没有提供 SQL_DELETE_ROW,但根据回答,这似乎不是 SELECT-请求返回 "resultset"。所以很可能它不应该是“.Open”的运行,而是“.Execute”或“.ExecSQL”或类似的东西。

更新。它被添加 SQL_DELETE_ROW = 'DELETE FROM MEVENTS'; 证实了我之前和进一步的期望。几乎。常量名称建议您要删除一行,而查询文本说您删除所有行,我想知道这是正确的吗?..

此外,由于没有 "resultset" - .Exec.... 之后 .Close 没有任何内容 - 但如果有这样的 [=,您可以检查 .RowsAffected 112=] 在 DBX 中,查看实际计划删除多少行。

此外,不,此函数不会删除行,它只会安排删除行。在处理 SQL 时,您确实必须投入时间和精力来学习 TRANSACTIONS,否则您很快就会被副作用淹没。

特别是,您必须在此处提交删除事务。为此,您要么必须显式创建、启动并绑定到 IBQuery 事务,要么找出 IBQuery1.Commit; 它隐式使用了哪个事务。 .Rollback 例外。

是的,很无聊,诸如此类。你可能希望 IBX 足够聪明,偶尔为你做一次提交。但是,如果不通过事务隔离数据更改,您将很难重现来自各种 "race conditions".

的 "side effects"

示例

  FieldDefs.Clear;  // frankly, I do not quite recall if IBX has those, but probably it does.
  Fields.Clear;     // forget the customizations to the fields, and the fields as well
  Open;      // Make no Exception here          
  Close;
  Halt;  // << insert this line
  Result := 1;

试试这个,我打赌你的 table 不会被清除,尽管查询是 "opened" 和 "closed" 没有错误。

  1. 整个With SQL do begin怪物可以用单线SQL.Text := SQL_DELETE_ROW;代替。了解 TStrings class 在 Delphi 中的含义 - 它在 Delphi 图书馆的很多地方使用,因此了解此 class 服务将节省您很多时间和功能。

  2. 没有必要 Prepare 一次性查询,您执行后就忘记了。对不更改 SQL.Text 但仅更改参数的查询进行了准备,然后使用相同的文本但不同的值重新打开查询。 好吧,有时我确实使用(误用?)显式准备来确保库从服务器获取参数数据类型。但是在您的示例中,两者都没有。但是,您的代码不使用参数,并且您不使用许多相同的 neverchanging SQL.text 打开。因此,它变成了噪音,使打字时间更长,阅读更难。

  3. 尝试 ShowMessage(E.ClassName + ^M^J + E.Message) 或只是 Application.ShowException(E) - 没有必要让两个停止模态 windows 而不是一个。

  4. Datamodule1.IBQuery1.close; - 这实际上是回滚事务的地方,而不是仅仅关闭无论如何都没有打开的查询。

  5. 现在,让两个(或更多?)SQL 请求抛出一个 Delphi 查询对象的想法本身就值得怀疑。您对查询进行自定义,例如修复 DisplayFormat 或设置字段的事件处理程序,那么该查询就非常值得持续自定义。您甚至可以在设计时设置 DisplayFormat,为什么不呢。

争夺一个 TIBQuery 对象毫无意义 - 有多少就有多少。截至目前,您必须普遍而准确地推断出您程序的每个函数中 IBQuery1 内的文本。

这再次为未来的副作用创造了可能性。想象一下,你在某个地方做 function1; function2;,后来你决定需要交换它们并做 function2; function1;。你可以做到吗?但是,如果 function2 更改 IBQuery1.SQL.Text 并且 function1 取决于先前的文本怎么办?然后呢?

所以,基本上,对您的查询进行排序。应该有那些跨函数调用的查询,然后它们最好有一个专用的查询对象,不要过度使用不同的查询。并且应该有 "one time" 查询只在一个函数内部使用,从不在函数外部使用,例如 SQL_DELETE_ROW - 如果小心使用,您可能会过度使用这些查询。但更好的办法是重新制作这些函数,使它们的查询成为局部变量,除了它们自己之外没有人可见。

PS。看来你被 IBX 库困住了,那么我建议你看看这个扩展 http://www.loginovprojects.ru/download.php?getfilename=uploads/other/ibxfbutils.zip 除其他外,它还提供通用 insert/delete 函数,这些函数会在内部创建和删除临时查询对象,因此您不必考虑它。

交易管理仍由您牢记和控制。