我想制作一个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;
答案 0 :(得分:6)
由于我的评论得到了赞赏,这是扩展版本。
我个人认为不可能。
无论如何,你可以尝试一些事情:
确保只有您的应用程序可以在数据库上写入
像这样写一个触发器(伪代码!)
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)
或者像这样
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
如果可能的话,我个人会选择第3种选择。无论如何,第二个也很好。除非必要,否则我不会依赖第一个选项(例如:无法访问触发功能)
此处有更多信息:reference
答案 1 :(得分:2)
数据库应用程序不能将此功能作为标准提供,这很有趣:不仅仅是为了创建" timestamp字段,但是对于诸如自动增量id字段之类的内容,以及您在创建记录时可能要设置的任何杂项值,然后永远不允许更改...想知道原理是什么?
答案 2 :(得分: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;//
错误1362(HY000):触发后
中不允许更新NEW行接受由BEFORE替换的AFTER相同的触发器; 对我而言,这是一种反直觉的方式,但它有效
delimiter ;
UPDATE members SET id=11353 WHERE id=1353;
Query OK, 0 rows affected (0.00 sec)
Rows matched: 1 Changed: 0 Warnings: 0
答案 3 :(得分:1)
如果您使用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;
答案 4 :(得分:0)
您可以在这里做的是,当更新行时,您可以在表上写TRIGGER
。在该触发器中,您可以比较旧值和新值,如果它们不同,则可以使用旧值覆盖新值。
答案 5 :(得分:-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 ;