7

我在 MySQL 中有这个程序(不要费心去弄清楚它的作用,只需观察光标打开的部分)

/* PROCEDURE 1 : Post notification */
DROP PROCEDURE IF EXISTS AddNotificationOnPosts;

DELIMITER $$
CREATE DEFINER=`root`@`localhost` PROCEDURE `AddNotificationOnPosts`(arg_from_user INT(11),arg_on_post_id INT(11),arg_in_group_id INT(11))
BEGIN
    DECLARE num_rows INT DEFAULT NULL;
    DECLARE insert_result INT DEFAULT NULL;

    DECLARE done INT DEFAULT 0;
    DECLARE var_user_id INT DEFAULT NULL;
        DECLARE c1 CURSOR FOR 
        SELECT user_id 
        FROM user_rights 
        WHERE user_rights.right = 101 AND user_rights.group_id  = arg_in_group_id 
        ORDER BY user_id DESC;
    DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;

    IF(arg_from_user IS NULL OR arg_from_user = '')
    THEN
        SELECT "0" AS response;
    ELSEIF(arg_on_post_id IS NULL OR arg_on_post_id = '')
    THEN
        SELECT "0" AS response;
    ELSEIF(arg_in_group_id IS NULL OR arg_in_group_id = '')
    THEN
        SELECT "0" AS response;
    ELSE
        SELECT count(notification_id) FROM notifications_posts 
        WHERE 
        from_user = arg_from_user AND
        on_post_id = arg_on_post_id AND
        in_group_id = arg_in_group_id
        INTO num_rows;
    END IF;

    IF num_rows = 0
    THEN
        INSERT INTO notifications_posts(from_user,on_post_id,in_group_id) VALUES(arg_from_user,arg_on_post_id,arg_in_group_id);
        SELECT ROW_COUNT() INTO insert_result;

        IF insert_result > 0 
        THEN        
            /* Increment the notifications for every user*/
            OPEN c1;
            read_loop: LOOP
                FETCH c1 INTO var_user_id;
                    IF done THEN
                        LEAVE read_loop;
                    ELSE
                        IF NOT(var_user_id = arg_from_user)
                        THEN

                            /* UPDATING */
                            UPDATE user_info SET notifications = notifications + 1 WHERE user_info.user_id = var_user_id;

                            /* SELECTING RESULT */
                            SELECT
                            user_info.user_id,
                            messages,
                            tasks,
                            notifications,
                            messages+tasks+notifications AS total
                            FROM user_rights
                            INNER
                                JOIN user_info
                                ON user_info.user_id = user_rights.user_id
                            WHERE user_rights.right = 101 AND user_rights.group_id  = arg_in_group_id ;

                        END IF;
                    END IF;
            END LOOP;
            CLOSE c1;


        ELSE
            SELECT "0" AS response;
        END IF;

    ELSE
        SELECT "0" AS response;
    END IF;
END $$
DELIMITER ;

在这部分

            /* Increment the notifications for every user*/
            OPEN c1;
            read_loop: LOOP
                FETCH c1 INTO var_user_id;
                    IF done THEN
                        LEAVE read_loop;
                    ELSE
                        IF NOT(var_user_id = arg_from_user)
                        THEN

                            /* UPDATING */
                            UPDATE user_info SET notifications = notifications + 1 WHERE user_info.user_id = var_user_id;

                            /* SELECTING RESULT */
                            SELECT
                            user_info.user_id,
                            messages,
                            tasks,
                            notifications,
                            messages+tasks+notifications AS total
                            FROM user_rights
                            INNER
                                JOIN user_info
                                ON user_info.user_id = user_rights.user_id
                            WHERE user_rights.right = 101 AND user_rights.group_id  = arg_in_group_id ;

                        END IF;
                    END IF;
            END LOOP;
            CLOSE c1;

该过程选择数据,然后更新它(相信我,我是认真的),我真的需要在之后选择,因为我正在XML使用更改后的数据生成一个,所以:

1 为什么选择然后更新,因为我看到选择在更新下方

2 谁有这个“绝妙的主意”来做到这一点?

谢谢你。

4

3 回答 3

1

我解决了这个问题:SELECT语句必须在CURSOR LOOP.

于 2012-09-12T09:24:09.107 回答
1

当您在 sql-server 中有一批更新/删除和其他内容时,执行“命令”的顺序完全不确定。解决这个问题的方法是使用“exec”语句将“update”放在不同的批次中。所以尝试使用:

exec('UPDATE user_info SET notifications = notifications + 1 WHERE user_info.user_id =' + var_user_id); 

它现在应该可以工作了。

于 2012-09-12T08:48:31.270 回答
0

我希望更新和选择以正确的顺序执行,但是由于事务隔离,选择无法“看到”更新的结果。

我建议以下解决方案来解决此问题并通过消除后续选择中的连接来提高性能:

set @notification = 0;

/* UPDATING */
UPDATE user_info SET notifications = @notification := notifications + 1 WHERE user_info.user_id = var_user_id;

/* SELECTING RESULT */
SELECT
     user_info.user_id,
     messages,
     tasks,
     notifications,
     messages+tasks+@notifications AS total
 FROM user_rights
WHERE user_rights.right = 101 AND user_rights.group_id  = arg_in_group_id ;
于 2014-04-26T09:26:06.393 回答