при обновлении current_timestamp с SQLite - PullRequest
25 голосов
/ 05 июля 2011

Я хочу обновлять поле с текущей отметкой времени при каждом обновлении строки.

В MySQL я бы это делал, когда объявлял таблицу

LastUpdate TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL ON UPDATE CURRENT_TIMESTAMP

Но "при обновлении"часть не работает с SQLite.Я не смог найти способ сделать это автоматически, мне нужно объявить триггер?

EDIT : Для записи, вот мой текущий триггер:

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

Спасибо

Ответы [ 4 ]

21 голосов
/ 05 июля 2011

Да, вам нужно использовать триггер.(Просто проверяю: правильно ли работает ваш опубликованный триггер? На первый взгляд, он мне подходит.)

MySQL ON UPDATE CURRENT_TIMESTAMP - довольно уникальный, одноцелевой ярлык.Что есть, то есть;эта конструкция не может использоваться аналогично для любых других значений или для любых типов столбцов, кроме TIMESTAMP.(Обратите внимание, как эта функциональность определяется на странице типа TIMESTAMP вместо CREATE TABLE page , так как эта функция относится только к столбцам TIMESTAMP, а не к операторам CREATE TABLEв общем.) Стоит также упомянуть, что, хотя он специфичен для типа TIMESTAMP, SQLite даже не имеет различных типов даты / времени .

Насколько я знаю, нетдругие СУБД предлагают этот ярлык вместо использования фактического триггера.Из того, что я прочитал, для достижения этой цели на MS SQL, SQLite, PostgreSQL и Oracle необходимо использовать триггеры.


Последнее замечание для прохожих:

Это не следует путать с предложениями ON UPDATE в отношении ограничений внешнего ключа.Это нечто совершенно другое, что, вероятно, есть во всех СУБД, поддерживающих ограничения внешнего ключа (включая MySQL и SQLite).

3 голосов
/ 17 марта 2015

Джон прав насчет настроек SQLite по умолчанию, этот триггер приводит к бесконечному циклу. Чтобы избежать рекурсии, используйте предложение WHEN.

Следующее будет работать, даже если включена настройка recursive_triggers:

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;
0 голосов
/ 20 мая 2018

Есть более эффективный, красивый и чистый способ сделать это, например:

-- 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;

Код, подобный этому, был протестирован в моем проекте.Глубокое объяснение триггера sqlite можно найти здесь https://www.sqlite.org/lang_createtrigger.html

0 голосов
/ 29 сентября 2017
-- 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  
);  
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...