在mysql的存储过程开发中,经常需要获取上一步更新操作影响的行数,以此判断更新是否成功、是否需要执行后续补偿逻辑。ROW_COUNT函数是mysql内置的用于返回上一条DML语句影响行数的函数,非常适合在存储过程中完成这类需求。

ROW_COUNT函数基本说明
ROW_COUNT函数的作用是返回最近一次执行的INSERT、UPDATE、DELETE语句所影响的行数,它的返回值规则如下:
- 如果是UPDATE语句,返回被修改的行数,即使修改后的值和原值相同,也会被计入影响行数
- 如果是INSERT语句,返回插入的新行数
- 如果是DELETE语句,返回被删除的行数
- 如果上一条语句不是DML语句,返回-1
存储过程中使用ROW_COUNT获取更新行数示例
下面通过一个完整的存储过程示例,演示如何在更新操作后获取影响行数:
-- 创建测试表
CREATE TABLE IF NOT EXISTS test_user (
id INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(50) NOT NULL,
age INT DEFAULT 0
);
-- 插入测试数据
INSERT INTO test_user (username, age) VALUES ('张三', 20), ('李四', 25);
-- 创建存储过程,更新用户年龄并获取更新行数
DELIMITER //
CREATE PROCEDURE update_user_age(IN target_id INT, IN new_age INT, OUT affected_rows INT)
BEGIN
-- 执行更新操作
UPDATE test_user SET age = new_age WHERE id = target_id;
-- 获取更新影响的行数,赋值给输出参数
SET affected_rows = ROW_COUNT();
END //
DELIMITER ;
-- 调用存储过程,更新id为1的用户年龄为22
SET @affected = 0;
CALL update_user_age(1, 22, @affected);
-- 查看获取到的更新行数
SELECT @affected AS affected_rows;
上述存储过程中,先执行UPDATE语句更新指定id的用户年龄,紧接着调用ROW_COUNT()函数获取这次更新操作的影响行数,赋值给输出参数affected_rows,调用方就可以通过该参数拿到对应的行数。
使用注意事项
ROW_COUNT的作用范围
ROW_COUNT函数只记录最近一次DML操作的影响行数,如果在获取之前执行了其他DML语句,之前的行数会被覆盖。比如下面的逻辑就会有问题:
DELIMITER //
CREATE PROCEDURE wrong_demo()
BEGIN
UPDATE test_user SET age = 30 WHERE id = 1;
-- 中间执行了其他DML操作,会覆盖之前的ROW_COUNT值
INSERT INTO test_user (username, age) VALUES ('王五', 28);
-- 此时获取的是INSERT的影响行数,不是UPDATE的
SELECT ROW_COUNT() AS wrong_rows;
END //
DELIMITER ;
和FOUND_ROWS的区别
很多开发者会混淆ROW_COUNT和FOUND_ROWS,两者的作用完全不同:
| 函数 | 作用 | 适用场景 |
|---|---|---|
| ROW_COUNT() | 返回上一条DML语句影响的行数 | 获取INSERT、UPDATE、DELETE的影响行数 |
| FOUND_ROWS() | 返回上一条SELECT语句不带LIMIT时的总行数 | 获取分页查询的总记录数 |
事务中的表现
如果在事务中执行更新操作,即使后续事务回滚,ROW_COUNT返回的行数也不会改变,它只记录语句执行时的影响行数,和事务是否提交无关。
常见问题解答
为什么获取的ROW_COUNT是0
如果更新条件没有匹配到任何记录,或者更新的值和原有值完全相同,ROW_COUNT会返回0。比如更新一个不存在的用户id,或者把用户年龄改成原来的值,都会返回0。
可以在存储过程外使用ROW_COUNT吗
可以,ROW_COUNT是会话级别的函数,在存储过程外执行DML语句后也可以直接调用,不过在存储过程中使用可以更方便地把行数传递给调用方。