sql >> データベース >  >> RDS >> Mysql

MySQLトリガーの例外/失敗情報をテーブルまたは変数に保存する方法

    DECLARE CONTINUE HANDLERでハッキングを見つけました およびGET DIAGNOSTICS CONDITION 、と思ったので、ここで共有する必要があります。

    これが、両方のデータベースのusersのバックアップ(同期)を維持する完全な最終スクリプトです。 表の意味は、test_db1の更新です。 (これをproductionDBと呼ぶ場合があります)はtest_db2で発生します (これをstagingDBと呼ぶ場合があります):

    /*
    Create two databases:
        1. `test_db1`
        2. `test_db2`
    and execute below create *Table script* on both databases.
    after that execute *Triggers Script* on `test_db1` only..
    */
    
    /*
        TABLE STRUCTURE FOR `users`
    */
    
    DROP TABLE IF EXISTS `users`;
    CREATE TABLE IF NOT EXISTS `users` (
      `id` int(11) AUTO_INCREMENT NOT NULL,
      `name` varchar(30) NOT NULL,
      `age` int(11) NOT NULL,
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
    
    /*
        TABLE STRUCTURE FOR `errors`
    */
    
    DROP TABLE IF EXISTS `errors`;
    CREATE TABLE IF NOT EXISTS `errors` (
      `id` int(11) AUTO_INCREMENT NOT NULL,
      `code` varchar(30) NOT NULL,
      `message` TEXT NOT NULL,
      `query_type` varchar(50) NOT NULL,
      `record_id` int(11) NOT NULL,
      `on_db` varchar(50) NOT NULL,
      `on_table` varchar(50) NOT NULL,
      `emailed` TINYINT DEFAULT 0,
      `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
    
    /*
        TRIGGERS SCRIPTS FOR INSERT, UPDATE AND DELETE OPERATIONS
    */
    
    DELIMITER //
    
    -- TRIGGER FOR INSERT
    DROP TRIGGER IF EXISTS `test_db1_users_ai`;
    CREATE TRIGGER `test_db1_users_ai` AFTER INSERT ON `users` FOR EACH ROW 
    BEGIN
        -- Declare variables to hold diagnostics area information
        DECLARE errorCode CHAR(5) DEFAULT '00000';
        DECLARE errorMessage TEXT DEFAULT '';
    
        -- Declare exception handler for failed insert
        DECLARE CONTINUE HANDLER FOR SQLEXCEPTION 
        BEGIN
          GET DIAGNOSTICS CONDITION 1
            errorCode = RETURNED_SQLSTATE, errorMessage = MESSAGE_TEXT;
        END;
    
        -- Perform the insert
        INSERT INTO `test_db2`.`users` (id, name, age) VALUES (NEW.id, NEW.name, NEW.age);
    
        -- Check whether the insert was successful
        IF errorCode != '00000' THEN
            INSERT INTO `errors` (code, message, query_type, record_id, on_db, on_table) VALUES (errorCode, errorMessage, 'insert', NEW.id, 'test_db2', 'users');
        END IF;
    END; //
    
    -- TRIGGER FOR UPDATE
    DROP TRIGGER IF EXISTS `test_db1_users_au`;
    CREATE TRIGGER `test_db1_users_au` AFTER UPDATE ON `users` FOR EACH ROW 
    BEGIN
        -- Declare variables to hold diagnostics area information
        DECLARE errorCode CHAR(5) DEFAULT '00000';
        DECLARE errorMessage TEXT DEFAULT '';
    
        -- Declare exception handler for failed insert
        DECLARE CONTINUE HANDLER FOR SQLEXCEPTION 
        BEGIN
          GET DIAGNOSTICS CONDITION 1
            errorCode = RETURNED_SQLSTATE, errorMessage = MESSAGE_TEXT;
        END;
    
        -- Perform the update
        UPDATE `test_db2`.`users`
            SET name = NEW.name,
                age = NEW.age
            WHERE id = NEW.id;
    
        -- Check whether the update was successful
        IF errorCode != '00000' THEN
            INSERT INTO `errors` (code, message, query_type, record_id, on_db, on_table) VALUES (errorCode, errorMessage, 'update', NEW.id, 'test_db2', 'users');
        END IF;
    END; //
    
    -- TRIGGER FOR DELETE
    DROP TRIGGER IF EXISTS `test_db1_users_ad`;
    CREATE TRIGGER `test_db1_users_ad` AFTER DELETE ON `users` FOR EACH ROW 
    BEGIN
        -- Declare variables to hold diagnostics area information
        DECLARE errorCode CHAR(5) DEFAULT '00000';
        DECLARE errorMessage TEXT DEFAULT '';
    
        -- Declare exception handler for failed insert
        DECLARE CONTINUE HANDLER FOR SQLEXCEPTION 
        BEGIN
          GET DIAGNOSTICS CONDITION 1
            errorCode = RETURNED_SQLSTATE, errorMessage = MESSAGE_TEXT;
        END;
    
        -- Perform the delete
        DELETE FROM `test_db2`.`users`
            WHERE id = OLD.id;
    
        -- Check whether the insert was successful
        IF errorCode != '00000' THEN
            INSERT INTO `errors` (code, message, query_type, record_id, on_db, on_table) VALUES (errorCode, errorMessage, 'delete', OLD.id, 'test_db2', 'users');
        END IF;
    END; //
    
    -- DELIMITER;
    

    これが他の人がここに来るときに役立つことを願っています。

    乾杯、



    1. c#.netでmysqlに接続します

    2. 1つのSQLスクリプトで子と親の行を削除します

    3. PHP / MySQL-配列データをJSONとして保存する、悪い習慣ですか?

    4. CachedRowSetはResultSetより遅いですか?