在SQLite数据库中存储日期时间值的最佳方法(Delphi)

时间:2010-01-21 01:10:48

标签: delphi datetime sqlite format

我将日期时间值存储在SQLite数据库中(使用Delphi和DISqlite库)。数据库的性质使得它永远不需要在计算机或系统之间传输,因此互操作性不是约束。我的重点是阅读速度。日期时间字段将被编入索引,我将对其进行大量搜索,并按顺序读取数千个日期时间值。

由于SQLite没有datetime值的显式数据类型,因此有几个选项:

  • 使用REAL数据类型并直接存储Delphi的TDateTime值:最快,加载时不从字符串转换;无法使用数据库管理器(如SQLiteSpy)调试日期,因为日期不会是人类可读的。不能使用SQLite日期函数(?)

  • 使用简单的字符串格式,例如YYYYMMDDHHNNSS:转换是必需的,但在CPU上相对容易(无需扫描分隔符),数据是人类可读的。仍然不能使用SQLite日期函数。

  • 做点别的事。推荐的做法是什么?

我已阅读http://www.sqlite.org/lang_datefunc.html,但没有提及要使用的数据类型,而且,在编程方面没有正式上学,我不太关注朱利安日期。为什么要额外转换?我会仔细阅读这些值,因此字符串和TDateTime之间的任何额外转换都会增加成本。

5 个答案:

答案 0 :(得分:8)

您可以使用SQLite支持的字符串格式之一,例如。 YYYY-MM-DD HH:MM:SS.SSS

它就像YYYYMMDDHHNNSS一样简单 - 您仍然不需要扫描分隔符,因为所有数字都是固定长度的 - 您将获得SQLite日期函数支持。

如果您需要SQLite日期功能支持,我会使用该方法。

如果没有,我建议使用REAL值。您仍然可以将它们相互比较(较高的数字在较晚的时间),并分别考虑日期和时间(分别在小数点之前和之后)而不转换为TDateTime。

答案 1 :(得分:5)

一个折衷方案是坚持使用REAL值,但是使用Delphi的DateTimeToJulianDate将它们存储为julian日期。这样他们仍然可以快速阅读,在对流中几乎没有性能损失,并且它们仍然采用德尔福以外的格式。

答案 2 :(得分:2)

为此,我通常使用Integer数据类型并存储Unix时间戳值(例如,自1-1-2000以来的eq#秒)。从TDateTime计算此t /等于/跳过/跳过86400并为'since'添加一个常量。

如果需要更高的精度您可以将DateTime用作FILETIME(例如int64),其增量为100 ns。 SysUtils中有转换例程,您的时间戳以UTC格式存储。

答案 3 :(得分:0)

如果您的关注点只是数据库级别的人类可读格式,则可以存储两个单独的字段,例如:

DELPHI_DATE REAL(DOUBLE,如果可能,但我不知道SQLite),已编入索引。您的所有程序化查询和比较都应使用此字段。

HUMAN_READABLE_DATE Varchar(23)格式为'YYYY-MM-DD HH:MM:SS.SSS'。也许索引(如果真的有必要)。大多数人工输入查询应包含此字段,您可以使用(如其他人所述)SQLite日期函数。

它有一些缺点:

  • 数据库和网络流量的空间消耗增长,
  • 插入操作会因为必要的转换而需要更多,
  • 如果在程序外更新,则值之间不会自动同步

如果它适合您的特殊需求,由您决定。

答案 4 :(得分:0)

我不知道这个答案是否适用于DISqlite库但是......
下面是一些代码,说明了使用Delphi 2010和Tim Anderson的SQLite3包装器对我有用的东西。

创建字段的SQL:

  sSQL :=  'CREATE TABLE [someTable] (' +
            '  [somefield1] VARCHAR(12),' +
            '  [somefield2] VARCHAR(12),' +
            '  [myDateTime] DATETIME );';

填充字段的SQL:

 sSQL := 'INSERT INTO someTable(somefield1, somefield2, myDateTime)' + 
         '  VALUES ( "baloney1", "baloney2","' + FloatToStr(Now) + '");';

从字段中检索数据的示例:

var
sDBFilePathString: string;
sl3tbl: TSqliteTable;
fsldb : TSQLiteDatabase;
FromdbDTField : TDateTime;

begin
   ...
   ... 
    fsldb := TSQLiteDatabase.Create(sDBFilePathString); 
    sl3tbl := fsldb.GetTable('SELECT * FROM someTable');
    FromdbDateTime := StrToFloat(sl3tbl.FieldAsString(sl3tbl.FieldIndex['myDateTime']));
    Showmessage('DT: ' + DateTimeToStr(FromdbDTField));
end;

结果:

**DT: 10/10/2013 1:09:53 AM**

就像我在第一行中提到的那样 - 我不知道这是否适用于DISqlite库,但是如果它能够以一种非常干净的方式处理事情。 我留给你让它变得更漂亮或更优雅。