Calling stored procedure sequentially from .sql file

后端 未结 1 635
小蘑菇
小蘑菇 2021-01-25 04:56

I\'m stuck here.

I\'ve got a Procedure that I want to run X* times in a row. (*X is couple of thousands times)
The procedure based on input data does this:
1. Lo

相关标签:
1条回答
  • 2021-01-25 05:58

    This isn't really a solution, but a workaround.

    Just to clarify, summary tables had id column as PRIMARY KEY with AUTO_INCREMENT option and indexes on both user_id and action_id column.

    My investigation showed that although my procedure was looking for an entry that existed using WHERE user_id = u_id AND action_id = a_id in certain situations it didn't find it causing new row being inserted with the same user_id and action_id values - something I did not want.

    Debugging the procedure showed that the summary row I was looking for, although not accessible with WHERE user_id = u_id AND action_id = a_id condition, was properly returned when calling it's id - PRIMARY KEY.
    With this find I decided to change format of id column, from UNASIGNED INT with AUTO_INCEREMENT to a CHAR(32) which consisted of:

    <user_id>|<action_id>
    

    This meant that I knew exactly what the id of the row I wanted is even before it existed. This solved the problem really. It also enabled me to use INSERT ... ON DUPLICATE KEY UPDATE ... construct.

    Below my updated procedure:

    CREATE PROCEDURE `NEW_ACTION`(
      IN a_date TIMESTAMP,
      IN u_name VARCHAR(255),
      IN a_name VARCHAR(255),
      IN a_chars INT,
      IN url VARCHAR(255),
      IN ip VARCHAR(15))
      SQL SECURITY INVOKER
    
    lbl_proc: BEGIN
        DECLARE a_id, u_id, a_day, a_month, error INT;
        DECLARE us_id, usd_id, usm_id CHAR(48);
        DECLARE sep CHAR(1);
        DECLARE CONTINUE HANDLER FOR SQLSTATE '23000' SET error = 1;
    
        SET sep = '|';
        SET error = 0;
        SET a_day = DATE_FORMAT(SUBSTRING(a_date ,1,10), '%Y%m%d');
        SET a_month = SUBSTRING(a_day, 1, 6);
    
        /* RETREIVING action.id */
        SET a_id = (SELECT `id` FROM `game_actions` WHERE `name` = a_name);
        IF a_id IS NULL THEN
          SELECT 'error';
          LEAVE lbl_proc;
        END IF;
    
        /* RETREIVING users.id */
        SET u_id = (SELECT `id` FROM `game_users` WHERE `name` = u_name);
        IF u_id IS NULL THEN
          INSERT INTO `game_users` (name) VALUES (u_name);
          SET u_id = LAST_INSERT_ID();
        END IF;
    
        /* SETTING summaries ids */
        SET us_id = CONCAT(u_id, sep, a_id);
        SET usd_id = CONCAT(a_day, sep, u_id, sep, a_id);
        SET usm_id = CONCAT(a_month, sep, u_id, sep, a_id);
    
        /* SAVING action AND UPDATING summaries */
        SET autocommit = 0;
        START TRANSACTION;
          INSERT INTO `game_users_actions` (`date`, `user_id`, `action_id`, `chars`, `url`, `ip`)
            VALUES (a_date, u_id, a_id, a_chars, url, ip);
          INSERT INTO `game_users_summaries` (`id`, `user_id`, `action_id`, `qty`, `chars`)
            VALUES (us_id, u_id, a_id, 1, a_chars)
            ON DUPLICATE KEY UPDATE qty = qty + 1, chars = chars + a_chars;
          INSERT INTO `game_users_summaries_days` (`id`, `day`, `user_id`, `action_id`, `qty`, `chars`)
            VALUES (usd_id, a_day, u_id, a_id, 1, a_chars)
            ON DUPLICATE KEY UPDATE qty = qty + 1, chars = chars + a_chars;
          INSERT INTO `game_users_summaries_months` (`id`, `month`, `user_id`, `action_id`, `qty`, `chars`)
            VALUES (usm_id, a_month, u_id, a_id, 1, a_chars)
            ON DUPLICATE KEY UPDATE qty = qty + 1, chars = chars + a_chars;   
    
          IF error = 1 THEN
            SELECT 'error';
            ROLLBACK;
            LEAVE lbl_proc;
          ELSE
            SELECT 'success';
            COMMIT;
          END IF;
      END
    

    Anyway, I still think there's some kind of a bug in MySQL, but I consider problem solved.

    0 讨论(0)
提交回复
热议问题