Подтвердить что ты не робот

При обновлении current_timestamp с помощью SQLite

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

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

LastUpdate TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL ON UPDATE CURRENT_TIMESTAMP

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

РЕДАКТИРОВАТЬ. Для записи здесь есть текущий триггер:

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

Спасибо

4b9b3361

Ответ 1

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

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

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


Одна последняя заметка для прохожих:

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

Ответ 2

Джон правильно относится к настройкам 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;

Ответ 3

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

Ответ 4

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

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