¿Cómo tener una marca de tiempo automática en SQLite?

132

Tengo una base de datos SQLite, versión 3 y estoy usando C # para crear una aplicación que use esta base de datos.

Quiero usar un campo de marca de tiempo en una tabla para concurrencia, pero noto que cuando inserto un nuevo registro, este campo no está configurado y es nulo.

Por ejemplo, en MS SQL Server, si uso un campo de marca de tiempo, esto es actualizado por la base de datos, no tengo que configurarlo yo mismo. ¿Es esto posible en SQLite?

Álvaro García
fuente

Respuestas:

212

Simplemente declare un valor predeterminado para un campo:

CREATE TABLE MyTable(
    ID INTEGER PRIMARY KEY,
    Name TEXT,
    Other STUFF,
    Timestamp DATETIME DEFAULT CURRENT_TIMESTAMP
);

Sin embargo, si su INSERTcomando establece explícitamente este campo en NULL, se establecerá en NULL.

CL.
fuente
55
Eso no es equivalente a la marca de tiempo de SQL Server porque se basa en el reloj del sistema; Si cambia el reloj, el valor podría ir hacia atrás. En SQL Server, los valores de la marca de tiempo siempre se incrementan.
Rory MacLeod
26
@ Matthieu No hay tipo de DATETIME datos , pero SQLite acepta cualquier cosa como tipo de campo .
CL.
44
@Matthieu Hay un tipo de datos DATETIME mencionado en SQLite en el enlace que ha proporcionado. Lea 2.2 Ejemplos de nombres de afinidad
Rafique Mohammed
66
Esto no parece cubrir las declaraciones de ACTUALIZACIÓN. Parece que un disparador es la única forma de hacer esto.
Dale Anderson
2
@CL Lo siento, tienes razón. Fusioné incorrectamente tu respuesta y la de Javed. Con DEFAULT (STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW', 'localtime'))uno realmente se obtienen valores significativos de microsegundos.
Dietmar
71

Puede crear el campo TIMESTAMP en la tabla en el SQLite, vea esto:

CREATE TABLE my_table (
    id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
    name VARCHAR(64),
    sqltime TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL
);

INSERT INTO my_table(name, sqltime) VALUES('test1', '2010-05-28T15:36:56.200');
INSERT INTO my_table(name, sqltime) VALUES('test2', '2010-08-28T13:40:02.200');
INSERT INTO my_table(name) VALUES('test3');

Este es el resultado:

SELECT * FROM my_table;

ingrese la descripción de la imagen aquí

mr.boyfox
fuente
No se puede agregar una columna con valor predeterminado no constante (ALTER TABLE "main". "Xxx_data" ADD COLUMN "created_date" TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP)
toing_toing
14

Al leer datefunc, un ejemplo práctico de finalización automática de fecha y hora sería:

sqlite> CREATE TABLE 'test' ( 
   ...>    'id' INTEGER PRIMARY KEY,
   ...>    'dt1' DATETIME NOT NULL DEFAULT (datetime(CURRENT_TIMESTAMP, 'localtime')), 
   ...>    'dt2' DATETIME NOT NULL DEFAULT (strftime('%Y-%m-%d %H:%M:%S', 'now', 'localtime')), 
   ...>    'dt3' DATETIME NOT NULL DEFAULT (strftime('%Y-%m-%d %H:%M:%f', 'now', 'localtime'))
   ...> );

Insertemos algunas filas de una manera que inicie la finalización automática de fecha y hora:

sqlite> INSERT INTO 'test' ('id') VALUES (null);
sqlite> INSERT INTO 'test' ('id') VALUES (null);

Los datos almacenados muestran claramente que los dos primeros son iguales pero no la tercera función:

sqlite> SELECT * FROM 'test';
1|2017-09-26 09:10:08|2017-09-26 09:10:08|2017-09-26 09:10:08.053
2|2017-09-26 09:10:56|2017-09-26 09:10:56|2017-09-26 09:10:56.894

¡Preste atención a que las funciones SQLite están entre paréntesis! ¿Qué tan difícil fue mostrarlo en un ejemplo?

¡Que te diviertas!

centurias
fuente
7

Puedes usar disparadores. funciona muy bien

CREATE TABLE MyTable(
ID INTEGER PRIMARY KEY,
Name TEXT,
Other STUFF,
Timestamp DATETIME);


CREATE TRIGGER insert_Timestamp_Trigger
AFTER INSERT ON MyTable
BEGIN
   UPDATE MyTable SET Timestamp =STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') WHERE id = NEW.id;
END;

CREATE TRIGGER update_Timestamp_Trigger
AFTER UPDATE On MyTable
BEGIN
   UPDATE MyTable SET Timestamp = STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') WHERE id = NEW.id;
END;
Rahmat Anjirabi
fuente
6

Para complementar las respuestas anteriores ...

Si está utilizando EF, adornar la propiedad con Anotación de datos [Marca de tiempo], luego vaya a OnModelCreating anulado, dentro de su clase de contexto, y agregue este código Fluent API:

modelBuilder.Entity<YourEntity>()
                .Property(b => b.Timestamp)
                .ValueGeneratedOnAddOrUpdate()
                .IsConcurrencyToken()
                .ForSqliteHasDefaultValueSql("CURRENT_TIMESTAMP");

Hará un valor predeterminado para cada dato que se insertará en esta tabla.

Rafael
fuente
¿Sabe cómo funciona Entity en Android, en una aplicación Xamarin? No he podido probar, aunque sería bueno reemplazar a DAL.
samis
No encuentro el paquete que se necesita para sqliteHasDefault. ¿Sabes qué paquete tengo que obtener de Nuget?
Simons0n
@ Simons0n, intente utilizar este espacio de nombres Microsoft.EntityFrameworkCore.Metadata.Builders.PropertyBuilder.
Rafael
2

puede usar la fecha y hora personalizada usando ...

 create table noteTable3 
 (created_at DATETIME DEFAULT (STRFTIME('%d-%m-%Y   %H:%M', 'NOW','localtime')),
 title text not null, myNotes text not null);

use 'NOW', 'localtime' para obtener la fecha actual del sistema; de lo contrario, mostrará algún tiempo pasado u otro en su base de datos después del tiempo de inserción en su base de datos.

Gracias...

Javed
fuente
1
Útil si necesita microsegundos; puede usar DEFAULT (STRFTIME ('% Y-% m-% d% H:% M:% f', 'NOW', 'localtime')) `. Solo decir DEFAULT CURRENT_TIMESTAMP solo te dará una granularidad de un segundo.
Dietmar
¡Esto definitivamente funciona! ¡preste atención a strftime () ya que está rodeado de paréntesis!
Centurian
0

Si utiliza el navegador SQLite DB, puede cambiar el valor predeterminado de esta manera:

  1. Elegir estructura de base de datos
  2. selecciona la mesa
  3. modificar tabla
  4. en su columna coloque bajo 'valor predeterminado' el valor: = (datetime ('now', 'localtime'))

Recomiendo hacer una actualización de su base de datos antes, porque un formato incorrecto en el valor puede causar problemas en el navegador SQLLite.

SJX
fuente