【问题标题】:Python: Number of rows affected by cursor.execute("SELECT ...)Python:受 cursor.execute("SELECT ...) 影响的行数
【发布时间】:2011-01-31 11:39:31
【问题描述】:

如何访问受以下因素影响的行数:

cursor.execute("SELECT COUNT(*) from result where server_state='2' AND name LIKE '"+digest+"_"+charset+"_%'")

【问题讨论】:

  • 这个问题没有意义。选择语句不会影响 任何 行。
  • 我认为目的是获取COUNT(*) 返回的行数,这意味着实际问题是“如何访问cursor.execute 的结果。
  • 也永远不要使用 python 字符串连接见initd.org/psycopg/docs/…,否则你将陷入痛苦的世界!
  • @Alex 的意思是,永远不要使用 python 字符串连接将变量值替换为 SQL 查询字符串。
  • 谢谢@Larsh :) 我的意思是在 Python 中的 SQL 查询上下文中。

标签: python sql rows database


【解决方案1】:

当使用count(*) 时,结果为{'count(*)': 9}

-- 其中 9 代表表中的行数,例如。

所以,为了获取唯一的数字,这在我的情况下工作,使用 mysql 8。

cursor.fetchone()['count(*)']

【讨论】:

    【解决方案2】:

    要获取所选行数,我通常使用以下方法:

    cursor.execute(sql)
    count = (len(cursor.fetchall))
    

    【讨论】:

      【解决方案3】:

      来自PEP 249,通常由 Python 数据库 API 实现:

      光标对象应响应以下方法和属性:

      […]

      .rowcount
      此只读属性指定最后一个 .execute*() 生成的行数(对于像“select”这样的 DQL 语句)或受影响的(对于像“update”或“insert”这样的 DML 语句)。

      但要小心——它接着说:

      如果没有对游标执行.execute*(),或者接口无法确定最后一次操作的行数,则该属性为-1。 [7]

      注意:
      DB API 规范的未来版本可以重新定义后一种情况,使对象返回 None 而不是 -1。

      因此,如果您已经执行了语句,并且它可以工作,并且您确定您的代码将始终针对同一 DBMS 的相同版本运行,这是一个合理的解决方案。

      【讨论】:

      • .rowcount for Select 似乎始终为 1
      • @Tie-fighter:生成了一行,包含值COUNT(*)。例如,如果您查询SELECT name FROM result WHERE server_state='2',您将得到零、一或多行。
      • SQLite alwaysSELECT 语句生成cursor.rowcount == -1,因为在您返回所有行之前它不知道将返回多少行;它是 SQLite 的迭代器。
      • 我发现@MartijnPieters cmets 通过连接器/Python 对 MariaDB 是正确的。对于 SELECT 语句,我总是返回 -1。
      • 我刚刚添加了一个警告来说明@MartijnPieters 的经历,我希望它可以节省未来的反对票,因为对于很多情况,这是一个很好的答案。
      【解决方案4】:

      在我看来,获取所选行数的最简单方法如下:

      当使用 fetch 命令(fetchall()、fetchone()、fetchmany())时,游标对象会返回一个包含结果的列表。要获取选定的行,只需打印此列表的长度。但这对 fetchall() 来说才有意义。 ;-)

      例子:

      print len(cursor.fetchall) 
      

      【讨论】:

      • 这更直接,它就像一个魅力。谢谢。
      • 不要忘记那之后光标是空的(在末尾)。
      • fetchall 将创建一个列表,如果我选择的数量超过 600000 !每个元组包含 10 个字段,这仅适用于小块数据并不是一个好的答案
      • 你从来没有在这里调用cursor.fetchall,所以文字代码,如所写,会产生类型错误。为什么要获取所有行只是为了在列表中使用len()?那只是浪费资源。使用SELECT COUNT(*) 让服务器进行计数。
      【解决方案5】:

      尝试使用fetchone

      cursor.execute("SELECT COUNT(*) from result where server_state='2' AND name LIKE '"+digest+"_"+charset+"_%'")
      result=cursor.fetchone()
      

      result 将保存一个包含一个元素的元组,其值为COUNT(*)。 所以要找到行数:

      number_of_rows=result[0]
      

      或者,如果您想一口气完成:

      cursor.execute("SELECT COUNT(*) from result where server_state='2' AND name LIKE '"+digest+"_"+charset+"_%'")
      (number_of_rows,)=cursor.fetchone()
      

      PS。尽可能使用参数化参数也是一个好习惯,因为它可以在需要时自动为您引用参数,并防止 sql 注入。

      参数化参数的正确语法取决于您的 python/数据库适配器(例如 mysqldb、psycopg2 或 sqlite3)。它看起来像

      cursor.execute("SELECT COUNT(*) from result where server_state= %s AND name LIKE %s",[2,digest+"_"+charset+"_%"])
      (number_of_rows,)=cursor.fetchone()
      

      【讨论】:

      • 用普通 Python 字符串替换构建语句不是首选方法。或者正如官方文档所说的那样"Never do this -- insecure!"。请改用? 语法。
      • 在 3.5 中不工作,需要 fetchall 进行计数,然后重新 fetch 进行处理。
      • @AlexeiMartianov:不确定您做了什么或使用了什么数据库适配器,但这在 Python 3.5 上运行良好,几乎可以使用任何数据库适配器。如果没有你的确切代码不起作用,我不得不假设问题是本地的。
      • @lmichelbacher:这就是为什么 Unutbu 已经在答案中介绍了如何使用 SQL 参数的原因。
      【解决方案6】:

      执行返回的行数:

      rows_affected=cursor.execute("SELECT ... ")
      

      当然,正如AndiDog已经提到的,你可以随时通过访问游标的rowcount属性来获取行数,以获取最后一次执行的计数:

      cursor.execute("SELECT ... ")
      rows_affected=cursor.rowcount
      

      来自python MySQLdb的内联文档:

       def execute(self, query, args=None):
      
          """Execute a query.
      
          query -- string, query to execute on server
          args -- optional sequence or mapping, parameters to use with query.
      
          Note: If args is a sequence, then %s must be used as the
          parameter placeholder in the query. If a mapping is used,
          %(key)s must be used as the placeholder.
      
          Returns long integer rows affected, if any
      
          """
      

      【讨论】:

      • +1 Boaz, "rows_affected=cursor.rowcount" 绝对是最好的答案。它不需要额外的查询,因为该值始终存在。 rowcount 对于确定通过查询插入、更新、删除或检索的记录数很有用。
      • 根据已经提到的PEP 249cursor.execute 方法返回的值不再被定义(在之前的规范版本中,它应该像 Boaz 的示例一样工作)。规范明确建议使用更灵活的.rowcount 属性,因为execute 方法返回的值取决于数据库接口实现。
      • @Boaz -- 我发现这种方法不适用于 MariaDB 10.4.17、Python 2.7.8 和 Connector/Python 2.0.4。可悲的是,我找不到任何适用于该工具组合的已发布方法。我终于不得不遍历行并自己计算它们!
      • 一个很好的答案,不需要再次编码或与服务器通信,也不会消耗任何内存,谢谢
      • cursor.rowcount可以留在-1。 PEP 规范将此留给数据库适配器,因此不能保证它适用于所有数据库。 cursor.execute()的返回值不是PEP规定的,有些数据库驱动(比如sqlite3)返回的是游标,而不是行数。
      猜你喜欢
      • 1970-01-01
      • 2021-01-26
      • 2011-10-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多