0

これが私の問題です。次のタスクを実行するためのストアドプロシージャを作成しました。表eventsには、存在しなくなった会場で存在する可能性のあるイベントがあります。すべてのイベントが会場に関連付けられているわけではありませんが、会場IDフィールドに整数値があるイベントはNULLです(またはゼロになる可能性がありますが、それが考慮されます)。定期的に会場はシステムから削除されますが、その場合、その会場に関連付けられているすべてのイベントをその正確な時間に削除することはできません。代わりに、後で定期的にタスクが実行され、会場テーブルの既存のレコードを参照しなくなった会場IDを持つすべてのイベントが削除されます。このためのストアドプロシージャを作成しましたが、機能しているようです。

これはストアドプロシージャです。

DROP PROCEDURE IF EXISTS delete_synced_events_orphans;
DELIMITER $$
CREATE PROCEDURE delete_synced_events_orphans()
BEGIN 

    DECLARE event_count int(11) DEFAULT 0;
    DECLARE active_event_id int(11) DEFAULT 0;
    DECLARE active_venue_id int(11) DEFAULT 0;
    DECLARE event_to_delete_id int(11) DEFAULT NULL;

    CREATE TEMPORARY TABLE IF NOT EXISTS possible_events_to_delete (
        event_id int(11) NOT NULL,
        venue_id_temp int(11) NOT NULL
    ) engine = memory;

    # create an "array" which is a table that holds the events that might need deleting
    INSERT INTO possible_events_to_delete (event_id, venue_id_temp) SELECT `events`.`id`, `events`.`venue_id` FROM `events` WHERE `events`.`venue_id` IS NOT NULL AND `events`.`venue_id` <> 0;
    SELECT COUNT(*) INTO `event_count` FROM `possible_events_to_delete` WHERE 1;

    detector_loop: WHILE `event_count` > 0 DO
        SELECT event_id INTO active_event_id FROM possible_events_to_delete WHERE 1 LIMIT 1;
        SELECT venue_id_temp INTO active_venue_id FROM possible_events_to_delete WHERE 1 LIMIT 1;

        # this figures out if there are events that need to be deleted
        SELECT `events`.`id` INTO event_to_delete_id FROM `events`, `venues` WHERE `events`.`venue_id` <> `venues`.`id` AND `events`.`id` = active_event_id AND `events`.`venue_id` = active_venue_id;

        #if no record meets that query, the active event is safe to delete
        IF (event_to_delete_id <> 0 AND event_to_delete_id IS NOT NULL) THEN
            DELETE FROM `events` WHERE `events`.`id` = event_to_delete_id;
            #INSERT INTO test_table (event_id_test, venue_id_temp_test) SELECT `events`.`id`, `events`.`venue_id` FROM `events` WHERE `events`.`id` =  event_to_delete_id;
        END IF;

        DELETE FROM possible_events_to_delete WHERE `event_id` = active_event_id AND `venue_id_temp` = active_venue_id;
        SET `event_count` = `event_count` - 1;

    END WHILE;

END $$
DELIMITER ;

問題の2つのテーブルのテーブル構造は次のとおりです。

CREATE TABLE IF NOT EXISTS events (
    id int(11) NOT NULL,
    event_time timestamp NOT NULL,
    venue_id_temp int(11) NOT NULL
);

CREATE TABLE IF NOT EXISTS venues (
    event_id int(11) NOT NULL,
    venue_id_temp int(11) NOT NULL
);

ストアドプロシージャは記述どおりに機能しますが、より適切に実行できるようにする方法について知りたいと思います。目標を達成するために多くの追加処理を行っているようです。手元のデータをクエリするためのより良い方法はありますか、それとも私が知らない他のより便利なコマンドやキーワードがありますか?これにより、このタスクをより適切に完了することができます(行数が少なくなり、計算が少なくなります)。私はまだストアドプロシージャの使用方法を学んでいるので、可能な限り実用的にタスクを完了するためにそれらを使用しています。この特定のクエリを作成して、MySQLのすべての機能をより有効に活用する方法を理解したいと思います。皆さんありがとうございます。

4

1 に答える 1

2

Everithingははるかに簡単です:

DROP PROCEDURE IF EXISTS delete_synced_events_orphans;
DELIMITER $$
CREATE PROCEDURE delete_synced_events_orphans()
BEGIN 

  DELETE
    FROM `events`
    WHERE `venue_id` IS NOT NULL AND `venue_id` <> 0
      AND `venue_id` NOT IN (SELECT `id` FROM `venues`)
  ;

END $$
DELIMITER ;

それでおしまい。:)

あなたは、MySQLにあなたのタスクを完了する方法を言わせようとして、必然的に考えます。しかし、SQLは宣言型言語であり、をすべきかを言うために設計されています。

于 2012-12-12T16:07:24.723 に答える