0

次のように定義された、作業中の2つのテーブルがあります。

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 AND dns_addresses_resolved.resolved_address が存在しない場合は行を挿入
  2. 重複キー {in dns_addresses_resolved} UPDATE last_resolved = NOW()
  3. ここが引っかかる部分です。dns_addresses_resolved.resolved_address が変更されたら、現在その行にあるデータを に移動しますdns_addresses_resolved_archive。この最後の部分を行うためにトリガーを使用することを検討していましたが、解決済みのアドレスが変更されたときに行き詰まります。

以下に示すように、3つの部分のうち2つを思いついたと思います。誰かが私のためにこれに光を当てることができると思っていました! これを行うためにコード内のロジックを使用できることはわかっていますが、学習は楽しいので、自分自身を苦しめています。

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()); 終わり

また、私がやろうとしていることをより論理的に行う方法を誰かが持っているなら、私は提案を受け入れる以上のものです. ご意見をお待ちしております。

編集:「アドレス」への更新は失敗し、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

トリガーが私がやろうとしていることに対する最も論理的な解決策のように思えるのに、なぜこのトリガーが ON UPDATE で SQL エラーを引き起こすのでしょうか?

4

1 に答える 1

0

resolved_addressへの変更の場合、複合主キーはそのid/resolved_address組み合わせには存在しないため、重複を取得することはありません。この場合、ストレート挿入が発生します。idまた、更新がトリガーされるように別のインデックスに対処したとしても、更新がトリガーされたかどうかを知る方法がないため、UPDATEトリガーが機能するとは思いません。タイムスタンプは更新するか、新しいresolved_addressものが提供されたときのものである必要があります。

サーバーに対する単一のクエリでこれを実行しようとしていると推測していますが、本質的には2つの一意のインデックス( に1つと に1つ)があるため、それに対する明確な解決策があるかどうかはわかりませidん。挿入しようとしたときにエントリが既に存在する場合に、異なる動作を提供したい。idresolved_address

私の推測では、(単一のデータベース呼び出しが必要な場合) ストアド プロシージャを作成するか、目的を達成するために複数のクエリを使用する必要があります。

于 2013-06-03T23:00:39.780 に答える