MySQL插入新行,重复键更新,如果一个键更改则触发

时间:2013-06-03 22:40:12

标签: 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不存在则INSERT行
  2.   
  3. ON DUPLICATE KEY {in dns_addresses_resolved} UPDATE last_resolved = NOW()
  4.   
  5. 这是我被困住的部分。当dns_addresses_resolved.resolved_address更改时,移动数据   目前在dns_addresses_resolved_archive的那一行。我曾是   看着使用触发器完成最后一部分,但是我遇到了困难   是刚刚resolve_address更改。
  6.         

    我想我想出了三个部分中的两个,如下所示   而我只是想知道任何人都可以对此有所了解   我!我知道我可以在代码中使用逻辑来做到这一点,但我是   让生活变得艰难,因为......好吧,学习很有趣!

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

    ?,NOW(),NOW())ON DUPLICATE KEY UPDATE 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

         

    如果有人更合乎逻辑,我也不仅仅接受建议   做我正在做的事情的方式。我很喜欢你的意见!

编辑:我想出了一个触发器,虽然对'address'的更新失败了,导致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错误更新?

1 个答案:

答案 0 :(得分:0)

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

我猜你是想通过针对服务器的单个查询来完成这项工作,但我不知道你是否有一个干净的解决方案,因为实质上你有两个独特的索引(一个在{{1如果在尝试插入时条目已经存在,那么您希望为idid提供不同的行为。

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