2010-01-21 36 views
8

Voy a almacenar valores de fecha y hora en una base de datos SQLite (usando Delphi y la biblioteca DISqlite). La naturaleza de la base de datos es tal que nunca será necesario transferirla entre computadoras o sistemas, por lo que la interoperabilidad no es una restricción. Mi enfoque en cambio está en la velocidad de lectura. El campo de fecha y hora será indexado y lo buscaré mucho, además de leer en miles de valores de fecha y hora en secuencia.Forma óptima de almacenar valores de fecha y hora en la base de datos SQLite (Delphi)

Desde SQLite no tiene un tipo de datos explícita para los valores de fecha y hora, hay varias opciones:

  • utilización tipo de datos REAL y los valores tDateTime tienda de Delphi directamente: más rápido, sin conversión de cadena en la carga; imposible depurar fechas usando un administrador de db como SQLiteSpy, ya que las fechas no serán legibles por humanos. No se pueden usar las funciones de fecha de SQLite (?)

  • use un formato de cadena simple, p. YYYYMMDDHHNNSS: se requiere conversión, pero es relativamente fácil para la CPU (no es necesario buscar separadores), los datos son legibles por el ser humano. Aún no puede usar las funciones de fecha de SQLite.

  • hacer otra cosa. ¿Qué es lo que se recomienda hacer?

He leído http://www.sqlite.org/lang_datefunc.html pero no hay ninguna mención de qué tipo de datos a utilizar, y, al no ser educados formalmente en la programación, no lo bastante asimilo el foco en fechas julianas. ¿Por qué la conversión adicional? Leeré mucho estos valores, por lo que cualquier conversión adicional entre cadenas y TDateTime agrega un costo significativo.

+0

También he visto http://stackoverflow.com/questions/1933720/how-do-i-insert-datetime-value-into-a-sqlite-database pero no responde mi pregunta sobre qué La forma óptima es, o hay una razón realmente convincente para preferir el formato de cadena ISO (y las conversiones asociadas) sobre la inserción directa de los valores TDateTime de Delphi. –

Respuesta

8

Puede usar uno de los formatos de cadenas admitidos por SQLite, p. Ej. YYYY-MM-DD HH:MM:SS.SSS.

Sería tan fácil como YYYYMMDDHHNNSS - aún no necesitaría buscar separadores, ya que todos los números son de longitud fija - y obtendría la compatibilidad con la función de fecha de SQLite.

Si necesita compatibilidad con la función de fecha SQLite, yo elegiría ese método.

De lo contrario, recomendaría utilizar los valores REAL. Todavía puede compararlos entre sí (los números más altos son más adelante en el tiempo) y considerar la fecha y la hora por separado (antes y después del punto decimal, respectivamente) sin convertir a TDateTime.

+0

He utilizado esta solución ASCII en gran medida, con CSV y otras bases de datos, y es lo que haría. Además, las funciones de fecha de SQLite funcionan. Ganar ganar ganar. –

5

Un compromiso sería quedarse con los valores REALES, pero almacenarlos como fechas julianas mediante el uso de DateTimeToJulianDate de Delphi. De esta manera, permanecen rápido para leer, se pierde poco rendimiento en la convección, y todavía están en un formato que tiene sentido fuera de Delphi.

+0

Utilicé valores REALES antes, una desventaja es que los valores en la base de datos no son ** legibles por el hombre **, y esto es inconveniente cuando se depura/analiza usando una herramienta SQL. –

2

Para esto generalmente utilizo un tipo de datos Integer y almaceno el valor de marca de tiempo de Unix por igual (eq # segundos desde 1-1-2000 por ejemplo). Calcular esta t/desde un TDateTime equivale a multiplicar/bucear con/por 86400 y agregar una constante para el 'since'.

Si necesita más precisión Puede usar DateTime como FILETIME (por ejemplo, int64) que tiene incrementos de 100 ns. Existen rutinas de conversión en SysUtils para eso y su marca de tiempo se almacena en UTC.

0

Si su preocupación es único formato legible por humanos a nivel de base de datos, puede almacenar dos campos separados, por ejemplo:

DELPHI_DATE real (DOBLE, si es posible, pero no sé SQLite), indexado . Todas sus consultas programáticas y comparaciones deberían usar este campo.

HUMAN_READABLE_DATE Varchar (23) con el formato 'YYYY-MM-DD HH: MM: SS.SSS'. Tal vez indexado (si es realmente necesario). La mayoría de las consultas de entrada de humanos debe incluir este campo y puede usar (como dijeron otros) las funciones de fecha de SQLite.

tiene algunos inconvenientes: el consumo

  • espacio en la base de datos y el tráfico de la red crece,
  • operaciones de inserción tendrán un poco más porque la conversión es necesario,
  • sin sincronización automática entre los valores si actualizados fuera de su programa

Si es adecuado para sus necesidades particulares, es su decisión.

0

No sé si esta respuesta se aplica a la biblioteca DISqlite pero ...
A continuación se muestra un código que ilustra lo que funciona para mí utilizando Delphi 2010 y el envoltorio SQLite3 de Tim Anderson.

SQL para crear el campo:

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

SQL para poblar campo:

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

Ejemplo de recuperación de datos de campo:

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; 

Resultado:

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

Como mencioné en la primera línea: no sé si esto funcionará con la biblioteca DISqlite, pero si lo hace es una manera bastante limpia de manejar las cosas. Te dejo hacer las cosas más lindas o más elegantes.

Cuestiones relacionadas