题
由于一致性原因,我想在无法修改的关系中制作一列。
背景故事是我有一个:n关系,其中“连接”关系具有其他值。我不希望任何人都能更改关系合作伙伴的ID。
到目前为止,我提出了什么:
创建一个检查新值是否与旧值相同的触发器。但是,如果条件被证明是正确的,我不知道如何否认更新动作。
到目前为止,这是我的触发因素:
CREATE TRIGGER deny_nton_change BEFORE UPDATE ON Schueler_in_Klasse
FOR EACH ROW BEGIN
IF NEW.Schueler_ID != OLD.Schueler_ID OR NEW.Klasse_ID != OLD.Klasse_ID THEN
END IF;
END;
解决方案
而不是中止更新,而只是覆盖它?
...
FOR EACH ROW BEGIN
SET NEW.Schueler_ID = OLD.Schueler_ID;
SET NEW.Klasse_ID = OLD.Klasse_ID;
END
其他提示
通过使用信号,一种相当不错的干净方式流产和返回可读的错误消息是:
信号sqlstate'45000'设置message_text ='schueler_id和klasse_id可能不会更改!';
请确保您的MySQL版本支持此功能,它是在MySQL 5.5中引入的。在早期版本中,您需要黑客攻击,例如将不存在的字段插入不存在的表。
正如GBN所提到的那样,用旧值覆盖新值也是一个不错的选择。
我实际上学到了一种流产触发器的后alley方法. 。这是非常粗略的,但是由于MySQL的存储过程语言未实施信号处理,因此起作用。它充其量可以模仿。
第11章,本书的第254-256页 MySQL存储过程编程 在子标题下 “用触发器验证数据” 建议将角色字符串选择为虚拟整数(就语法而言,这是正确的,但是死于执行[无双关语]):
CREATE TRIGGER deny_nton_change BEFORE UPDATE ON Schueler_in_Klasse
FOR EACH ROW BEGIN
DECLARE dummy INT;
IF NEW.Schueler_ID != OLD.Schueler_ID OR NEW.Klasse_ID != OLD.Klasse_ID THEN
SELECT 'Cannot Carry Out This Trigger Any Further'
INTO dummy FROM table_you_know_does_not_exist WHERE 1=1 LIMIT 1;
END IF;
END;
实际上,如果您使用InnoDB,则可以整齐地进行此操作,而无需使用触发器。
仅使用一个列创建另一个表。该列应具有外键(因此本解决方案中的InnoDB要求),该列指向所讨论的原始表的不变列。
放置“更新限制”之类的限制。
总之:
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;
根据所有答案的组合,我读过的这是对我有用的东西:
delimiter $$ -- You may need this or not (in my visual client I need it, directly in console I don't)
create trigger deny_nton_change before update on surveys
for each row begin
if new.Schueler_ID != old.Schueler_ID OR new.Klasse_ID != old.Klasse_ID then
signal sqlstate '45000' set message_text = 'My own Error: Field is immutable';
end if;
end$$
delimiter ; -- You may need this or not
不隶属于 dba.stackexchange