6

我想制作一个TIMESTAMP字段DEFAULT CURRENT_TIMESTAMP,用于“创作时间”。但是,如果某人或某事发生了变化,TIMESTAMP,我的数据将不一致。

有没有一种方法可以确保它不会改变,除非我删除该行并重新插入它,而不是应用程序级别?


提供建议的答案后,我可以解决这样的问题

CREATE TRIGGER consistency1 BEFORE UPDATE ON table1
FOR EACH ROW
BEGIN
    IF NEW.creationtime != OLD.creationtime THEN
       SET NEW.creationtime = OLD.creationtime;
    END IF;
END;
4

6 回答 6

9

由于我的评论受到赞赏,这里是扩展版本。

我个人认为这是不可能的。

无论如何,您可以尝试以下几件事:

  1. 确保只有您的应用程序可以写入数据库

  2. 像这样写一个触发器(伪代码!)

    create trigger prevent_change_timestamp on tbl_name
    before update
    #fetch old row value
    #verify if the timestamp field has been changed
    #raise an error (any SQL error will do)
    
  3. 或者像这样

    create trigger revert_change_timestamp on tbl_name
    after update
    #fetch pre-change row value
    #update the row with the "old" value in place of the new one
    

如果可能的话,我个人会选择第三种选择。反正第二个也不错。除非必要,否则我不会依赖第一个选项(例如:无法访问触发功能)

更多信息在这里:参考

于 2013-07-02T11:38:44.173 回答
4

有趣的是,数据库应用程序不提供此功能作为标准:不仅适用于“创建的”时间戳字段,还适用于自动增量 id 字段以及您可能希望在创建记录时设置的任何杂项值和然后永远不允许被改变......想知道理由是什么?

于 2014-08-20T12:49:27.717 回答
1

我在 MySQL 5.1 中尝试过这个并得到了一个错误

DELIMITER //

CREATE TRIGGER member_update_0
    ->     AFTER UPDATE ON members
    ->     FOR EACH ROW
    -> BEGIN
    ->     IF NEW.id != OLD.id THEN
    ->        SET NEW.id = OLD.id;
    ->     END IF;
    -> END;//

ERROR 1362 (HY000): 触发器后不允许更新新行

接受相同的触发器,将 AFTER 替换为 BEFORE;对我来说,这是一种违反直觉的方法,但它确实有效

delimiter ;
UPDATE members SET id=11353 WHERE id=1353;
Query OK, 0 rows affected (0.00 sec)
Rows matched: 1  Changed: 0  Warnings: 0
于 2013-09-04T21:58:45.537 回答
0

你可以在这里做的是,TRIGGER当一行被更新时,你可以在表格上写一个。在该触发器中,您可以比较旧值和新值,如果它们不同,那么您可以用旧值覆盖新值。

于 2013-07-02T11:35:03.293 回答
0

如果您使用 InnoDB,实际上可以非常巧妙地做到这一点。

创建另一个只有一列的表。该列应该有一个指向相关原始表的不可变列的外键(因此在此解决方案中需要 innodb)。

设置“ON UPDATE RESTRICT”之类的限制。

总之:

CREATE TABLE original (
     ....
     immutable_column ...
     INDEX index1(immutable_column)
     ....
) ENGINE=INNODB;

CREATE TABLE restricter (
     .....
     col1,
     INDEX index2(col1),
     FOREIGN KEY (col1) REFERENCES original (immutable_colum) ON UPDATE RESTRICT ON DELETE CASCADE
) ENGINE=INNODB;
于 2014-07-13T07:19:29.220 回答
-1

将这个想法更进一步(对于我们这些仍然坚持使用旧版 MySQL 的人),您可以同时拥有一个受保护和默认的 create_stamp 和一个自动更新 update_stamp,如下所示:

如果您有一张桌子,例如

CREATE TABLE `csv_status` (
  `id` int(11) NOT NULL primary key AUTO_INCREMENT,
  `create_stamp` datetime not null,
  `update_stamp` timestamp default current_timestamp on update current_timestamp,
  `status` enum('happy','sad') not null default 'happy'
);

然后你可以在上面定义这些触发器

drop trigger if exists set_create_stamp ;
create definer = CURRENT_USER trigger set_create_stamp BEFORE INSERT on 
csv_status for each row
  set NEW.create_stamp = now();

drop trigger if exists protect_create_stamp ;
delimiter //
create definer = CURRENT_USER trigger protect_create_stamp BEFORE UPDATE on 
csv_status for each row
  begin
    if NEW.create_stamp != OLD.create_stamp then
    set NEW.create_stamp = OLD.create_stamp;
    end if;
  end;//
delimiter ;
于 2017-08-31T20:58:20.213 回答