web-dev-qa-db-fra.com

sur la mise à jour current_timestamp avec SQLite

Je souhaite mettre à jour un champ avec l'horodatage actuel chaque fois que la ligne est mise à jour.

Dans MySQL, je le ferais en déclarant la table

LastUpdate TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL ON UPDATE CURRENT_TIMESTAMP

Mais la partie "on update" ne fonctionne pas avec SQLite. Je ne pouvais pas trouver un moyen de le faire automatiquement. Dois-je déclarer un déclencheur?

EDIT: Pour mémoire, voici mon déclencheur actuel:

CREATE TRIGGER [UpdateLastTime]
AFTER UPDATE
ON Package
FOR EACH ROW
BEGIN
UPDATE Package SET LastUpdate = CURRENT_TIMESTAMP WHERE ActionId = old.ActionId;
END

Merci

22
Jonas

Oui, vous devez utiliser un déclencheur. (Je vérifie simplement: votre déclencheur affiché fonctionne-t-il correctement? À première vue, il me semble bien.)

Le ON UPDATE CURRENT_TIMESTAMP de MySQL est un raccourci unique et vraiment unique. C'est ce que c'est; cette construction ne peut pas être utilisée de la même manière pour toute autre valeur ou pour tout type de colonne autre que TIMESTAMP. (Notez comment cette fonctionnalité est définie sur la page de type TIMESTAMP au lieu de la page CREATE TABLE , cette fonctionnalité étant spécifique aux colonnes TIMESTAMP et non à CREATE TABLE en général.) dans un type TIMESTAMP, SQLite n'a même pas de types date/heure distincts .

Autant que je sache, aucun autre SGBDR n'offre ce raccourci au lieu d'utiliser un déclencheur réel. D'après ce que j'ai lu, des déclencheurs doivent être utilisés pour accomplir cela sur MS SQL, SQLite, PostgreSQL et Oracle.


Une dernière note pour les passants:

Cela ne doit pas être confondu avec les clauses ON UPDATE en relation avec les contraintes de clé étrangère. C'est quelque chose de complètement différent, ce que tous les SGBDR prenant en charge les contraintes de clé étrangère ont probablement (y compris MySQL et SQLite).

18
Wiseguy

John a raison sur les paramètres SQLite par défaut, ce déclencheur conduit à une boucle infinie. Pour éviter la récursivité, utilisez la clause WHEN.

Suivre fonctionnera même si le paramètre recursive_triggers est activé:

PRAGMA recursive_triggers=1;     --- test

CREATE TRIGGER [UpdateLastTime]
    AFTER UPDATE
    ON package
    FOR EACH ROW
    WHEN NEW.LastUpdate < OLD.LastUpdate    --- this avoid infinite loop
BEGIN
    UPDATE Package SET LastUpdate=CURRENT_TIMESTAMP WHERE ActionId=OLD.ActionId;
END;
2
aMarCruz
-- Describe UPDATELASTTIME  
CREATE TRIGGER [UpdateLastTime]  
    AFTER   
    UPDATE  
    ON test
    FOR EACH ROW   
    WHEN NEW.last_update_ts <= OLD.last_update_ts  
BEGIN  
    update test set last_update_ts=CURRENT_TIMESTAMP where id=OLD.id;  
END  

-- Describe TEST  
CREATE TABLE "main"."test" (  
    "id" INTEGER PRIMARY KEY AUTOINCREMENT,  
    "name" TEXT,  
    "last_update_ts" DATETIME DEFAULT CURRENT_TIMESTAMP  
);  
0
Jixster

Il existe une manière plus efficace, agréable et propre de le faire, par exemple:

-- List all required fields after 'OF' except the LastUpdate field to prevent infinite loop
CREATE TRIGGER UpdateLastTime UPDATE OF field1, field2, fieldN ON Package
BEGIN
  UPDATE Package SET LastUpdate=CURRENT_TIMESTAMP WHERE ActionId=ActionId;
END;

Le code comme celui-ci a été testé dans mon projet. Vous trouverez une explication détaillée du déclencheur sqlite ici https://www.sqlite.org/lang_createtrigger.html

0
Dmitrij