0

我有两个正在使用的表,定义如下。

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 DUPLICATE KEY {in dns_addresses_resolved} UPDATE last_resolved = NOW()
  3. 这是我卡住的部分。当 dns_addresses_resolved.resolved_address 发生变化时,将该行中当前的数据移动到dns_addresses_resolved_archive. 我一直在考虑使用触发器来完成最后一部分,但我遇到困难的地方是当 resolve_address 发生变化时。

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

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 值($oldTable.id、$oldTable.malware_id、$oldTable.type、$oldTable.ttl、$oldTable.resolved_address、$oldTable.first_resolved、NOW());结尾

如果有人有更合乎逻辑的方式来做我想做的事情,我也非常愿意接受建议。我会喜欢你的意见!

编辑:我想出了一个触发器,尽管对“地址”的更新失败,并导致一个 mysql 错误,我不知道为什么。错误是

错误 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 错误?

4

1 回答 1

0

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

我猜您正在尝试通过对服务器的单个查询来完成此操作,但我不知道您是否有一个干净的解决方案,因为本质上您有两个唯一索引(一个 onid和一个 on id, resolved_address)如果在尝试插入时已经存在条目,您希望提供不同的行为。

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

于 2013-06-03T23:00:39.780 回答