如何获取sqlalchemy中受影响的行数?

51 投票
5 回答
30860 浏览
提问于 2025-04-15 11:04

我有一个关于Python和sqlalchemy模块的问题。请问在sqlalchemy中,cursor.rowcount的对应是什么?

5 个回答

5

Shiplu的分析是完全正确的。

进一步讨论一下,下面是如何使用sqlalchemy在MySQL中显示更新后的行数,而不是匹配到的行数:创建引擎时需要加上一个标志client_flag=0

from sqlalchemy import create_engine
engine = create_engine(
    'mysql+pymysql://user:password@host:port/db', 
    connect_args={'client_flag':0}
)

再详细一点,MySQL返回的rowcount值取决于提供给C-API函数mysql_real_connect()CLIENT_FOUND_ROWS标志,具体可以参考MySQL文档

对于UPDATE语句,默认情况下,受影响的行数是实际改变的行数。如果在连接到mysqld时给mysql_real_connect()指定CLIENT_FOUND_ROWS标志,那么受影响的行数就是“找到”的行数,也就是WHERE条件匹配的行数。

这个标志的值是2(MySQL常量),在创建engine时,sqlalchemy会自动添加这个值,具体可以在这里看到。

connect_args中的client_flag值可以用来覆盖这个默认值。

注意:这可能会影响sane_rowcount的某些功能(这个功能似乎只在ORM中使用) - 在我的情况下,我只使用sqlalchemy的核心部分。在最后一个链接中:

# FOUND_ROWS must be set in CLIENT_FLAGS to enable
# supports_sane_rowcount.
32

其实,对于Postgres来说,没有办法准确知道这一点。

最接近的就是 rowcount。但是,rowcount 并不是受影响的行数,而是匹配的行数。你可以看看文档是怎么说的。

这个属性返回的是匹配的行数,这不一定等于实际被修改的行数。例如,一个UPDATE语句,如果设置的值和当前行的值一样,那么这行就没有实际变化。这样的行会被匹配,但不会被修改。在一些支持这两种风格的数据库中,比如MySQL,rowcount默认会在所有情况下返回匹配的行数。

所以在以下两种情况下,rowcount都会报告1。因为匹配的行数: 1

  1. update语句修改了一行。

     Query OK, 1 row affected (0.00 sec)
     Rows matched: 1  Changed: 1  Warnings: 0
    
  2. 执行了相同的update语句。

     Query OK, 0 row affected (0.00 sec)
     Rows matched: 1  Changed: 0  Warnings: 0
    
44

ResultProxy 对象还有一个叫做 rowcount 的属性。

撰写回答