在数据库操作中,corsor对象的rowcount属性如何统计SQL语句执行后的结果数量?
在数据库操作中,corsor对象的rowcount属性如何统计SQL语句执行后的结果数量?大家平时敲代码连数据库,有没有碰到过想算SQL跑了之后到底动了或查了多少行,盯着cursor.rowcount却摸不着头脑的时候?其实它不是“猜”出来的,得看SQL是查、改还是删,不同活儿它数数的法子不一样,弄明白这个,调接口、查bug都能少绕弯子。
先搞懂cursor.rowcount到底是啥“脾气”
好多新手刚碰cursor.rowcount,容易把它当成“万能计数器”,其实它像个“挑活的伙计”——只干自己能数的活儿,还得看SQL是啥类型。
- 它是“执行后”的数,不是“预想”的数:得等SQL真跑完了,cursor才会把数填进去。要是SQL没执行就瞅它,多半是0或者负数,白着急。
- 只认“有效操作”的行:比如你写了条查所有用户的SQL,但表里压根没用户,那rowcount就是0;要是改了5行数据,它就老老实实报5,不会多也不会少。
- 不同数据库的“小性子”得摸透:MySQL里查数据的rowcount可能不准(尤其用了某些引擎),但PostgreSQL、SQL Server里查数据基本靠谱;改删操作的话,大部分数据库都跟得紧。
不同SQL语句下rowcount怎么“数数”
咱们日常写的SQL就三类:查(SELECT)、改(UPDATE)、删(DELETE),还有增(INSERT),每类活儿rowcount的算法都不一样,得拆开说。
1. SELECT语句:查数据时的“数数逻辑”
查数据是用得最多的,但rowcount在这儿最容易“闹误会”。
- 数的是“游标扫过的行”:比如你查“select * from user where age>18”,cursor会从第一行符合条件的开始,一路扫到最后一行,rowcount就是扫过的总行数。但要注意——如果查询用了LIMIT,比如只取前10条,那rowcount可能只报10,哪怕符合条件有100条。
- 部分数据库的“特殊情况”:MySQL里InnoDB引擎查大表时,rowcount可能返回-1(表示“数不清”),这时候别慌,换个引擎(比如MyISAM)或者直接用len(cursor.fetchall())更准;PostgreSQL里查数据,只要游标没关,rowcount就准得很。
2. UPDATE/DELETE语句:改删数据时的“实打实计数”
改删数据是“动真格”的,rowcount在这儿最靠谱,因为它数的是真正被改掉或删掉的行。
- 按“影响行数”算:比如你写“update user set status=1 where city='北京'”,如果北京有23个用户,那rowcount就是23;要是没匹配到任何行,就是0。
- 要注意“条件坑”:比如你写“delete from order where create_time<'2023-01-01'”,但create_time字段里有空值,那这些空值的行不会被删,rowcount也不算它们——所以写条件时得盯紧字段里的“漏网之鱼”。
3. INSERT语句:插数据时的“简单计数”
插数据最简单,rowcount直接数成功插进去的行。
- 单条插入:比如“insert into user(name) values('张三')”,rowcount就是1;
- 批量插入:比如“insert into user(name) values('李四'),('王五')”,rowcount就是2;
- 要注意“重复键”:要是插入时触发了唯一键冲突,那冲突的那行不算,rowcount只算成功插进去的。比如你批量插5条,其中1条name重复,那rowcount就是4。
实际场景里用rowcount容易踩的“坑”及避坑法
光知道理论不够,实际写代码时总碰到“明明改了3行,rowcount却报0”的情况,咱们聊聊最常见的几个坑,还有怎么绕过去。
| 常见坑点 | 为啥会这样 | 咋解决 |
|----------|------------|--------|
| 查数据时rowcount是-1(MySQL) | InnoDB引擎为了快,不实时数大表的行 | 要么换MyISAM引擎,要么用len(cursor.fetchall())代替 |
| 改数据后rowcount比预期少 | SQL条件写错了(比如字段名拼错、大小写不对) | 先单独跑一遍SQL看影响行数,再核对条件 |
| 插数据后rowcount是0 | 触发了唯一键/主键冲突 | 插之前先查要插的数据存不存在,或者用INSERT IGNORE忽略冲突 |
| 游标没“刷新”就瞅rowcount | SQL还没执行完,或者游标没fetch数据 | 得等execute()执行完,再瞅rowcount;查数据的话,最好先fetch一下 |
用rowcount时的几个关键问答,帮你捋清楚
问:rowcount能用来判断“SQL有没有执行成功”吗?
答:不能。比如你删一条不存在的记录,rowcount是0,但SQL本身是成功的(没报错);只有当SQL语法错了、权限不够时,才会抛异常,这时候根本拿不到rowcount。
问:跨数据库用rowcount,要注意啥?
答:得记牢不同数据库的“小脾气”——比如MySQL查数据可能不准,PostgreSQL准;SQL Server里,查数据的rowcount要等游标fetch后才更新。最好写代码时加个“数据库类型判断”,针对性处理。
问:rowcount是“实时更新”的吗?
答:不是。比如你先执行了一条改5行的SQL,rowcount是5;接着又执行了一条改3行的SQL,rowcount会变成3——它会覆盖上一次的结果,所以每次执行SQL后都得赶紧瞅,别等下一条执行了再回头找。
举个真实例子,看看rowcount怎么用
我之前做电商项目时,写过个“批量取消超时订单”的功能:
1. 写SQL:“update order set status=0 where status=1 and create_time
3. 然后把这12返回给前端,告诉运营“成功取消了12笔超时订单”。
后来发现有时候rowcount是0,查了半天才发现——有个定时任务的SQL把时间条件写成了“create_time>now()-interval 30 minute”(多了个大于号),导致没匹配到任何订单。从那以后,我每次写改删SQL,都会先把条件单独跑一遍验证,再用rowcount核对。
其实cursor.rowcount没那么“玄乎”,它就是个“如实报数”的小帮手——你得先搞清楚SQL是啥类型,再摸透数据库的脾气,最后注意避开那些常见的坑,就能让它乖乖给你报准数。平时写代码时多试几次,比如故意写个错条件看看rowcount是啥样,慢慢就熟了。咱们做开发的,不就是跟这些“小细节”较劲,把活儿做扎实嘛!
【分析完毕】

红豆姐姐的育儿日常