2013-06-03 38 views
0

我有两个表,我正在使用,定义如下。MySQL插入新行,在重复键上更新,如果一个键更改,触发

CREATE TABLE dns_addresses_resolved (
    id INT(13) NOT NULL REFERENCES dns_addresses(id), 
    malware_id INT(13) REFERENCES malware_families(id), 
    type VARCHAR(10), 
    ttl int(10), 
    address VARCHAR(50), 
    first_resolved DATETIME, 
    last_resolved DATETIME, 
     PRIMARY KEY (id, address) 

) 

CREATE TABLE dns_addresses_resolved_archive (
    id INT(13) NOT NULL REFERENCES dns_addresses(id), 
    malware_id INT(13) REFERENCES malware_families(id), 
    type VARCHAR(10), 
    ttl int(10), 
    address VARCHAR(50), 
    first_resolved DATETIME, /* When was this IP first seen */ 
    archived_date DATETIME,  /* The date that the IP changes, and the 'old' IP is archived */ 
     PRIMARY KEY (id, address) 

) 

我试图做的是:

  1. 插入行如果dns_addresses_resolved.id和dns_addresses_resolved.resolved_address不存在
  2. ON last_resolved重复键{中} dns_addresses_resolved UPDATE = NOW()
  3. 下面是我卡住的部分。当dns_addresses_resolved.resolved_address更改时,将当前该行中的数据 移动到dns_addresses_resolved_archive。我是 看着使用触发器来做这最后一部分,但我卡住的地方 是刚刚resolved_address更改。

我在想,我想出了两个三个部分,如图下面 ,我只是想知道的任何人都可以提供一些线索就此对 我!我知道我可以在代码中使用逻辑来做到这一点,但我是 使自己的生活变得艰难,因为..好吧,学习很有趣!

INSERT INTO dns_addresses_resolved (id, type, ttl, resolved_address, first_resolved, last_resolved)  VALUES (?, ?, ?, 

?,NOW(),NOW())对重复密钥更新last_resolved = NOW()

CREATE TRIGGER dns_resolved_archive BEFORE UPDATE ON dns_addresses_resolved.resolved_address FOR EACH ROW BEGIN  INSERT 

INTO dns_addresses_resolved_archive VALUES($ oldTable.id, $ oldTable.malware_id,$ oldTable .type,$ oldTable.ttl, $ oldTable.resolved_address,$ oldTable.first_resolved,NOW()); END

我也比开放的建议,如果任何人有更多的逻辑 做我想做的事情的方式。我很喜欢你的输入!

编辑:我想出了一个触发器,虽然更新到'地址'失败,并导致一个mysql错误,我不知道为什么。该错误是

ERROR 1054(42S22):在 '字段列表'

起初似乎完全是直线前进未知列 'dns_addresses_resolved.id'。当我运行以下更新触发器,我得到错误。当我运行相同的查询没有触发器时,更新正常。

update dns_addresses_resolved set address = 'google.com' where id = 1; 

下面是我的触发器。

CREATE TRIGGER archive_old_dns_resolution 
BEFORE UPDATE ON dns_addresses_resolved 
FOR EACH ROW 
BEGIN 
    IF NEW.address <> OLD.address THEN 
     INSERT INTO dns_addresses_resolved_archive 
     VALUES ($oldTable.id, $oldTable.malware_id, $oldTable.type, $oldTable.ttl, $oldTable.address, $oldTable.first_resolved, NOW()); 
    END IF; 
END 

所以考虑到触发似乎是最合理的解决方案,我想要做的,为什么会发生这种触发引起更新SQL错误?

回答

0

如果更改为resolved_address,您将不会获得重复项,因为该组合的主键不会存在。在这种情况下会发生直插。我也不认为UPDATE触发器可以为你工作,因为即使你只为id寻址一个单独的索引以便触发更新,你也无法知道更新是否触发了时间戳应该更新或者提供新的resolved_address时。

我猜你试图用一个查询来完成这项工作,但我不知道你是否有一个干净的解决方案,因为本质上你有两个独特的索引(一个在id和一个在id,resolved_address),你想提供不同的行为,如果尝试执行插入时条目已经存在。

我的猜测是你需要创建一个存储过程(如果你想单个数据库调用),或者你需要使用多个查询来实现你想要做的事情。

+0

谢谢,迈克。这或多或少是我会来的结论。我只是希望有人会对我有一个神奇的答案:) – geudrik

+0

我找到了一个解决方案,但当触发器触发时更新失败。 OP已更新为包含我的触发器。 – geudrik

相关问题