【问题标题】:How to check if a result set is empty?如何检查结果集是否为空?
【发布时间】:2013-05-09 19:22:34
【问题描述】:

我有一个不返回任何命中的 sql 语句。例如,'select * from TAB where 1 = 2'

我想检查返回了多少行,

cursor.execute(query_sql)

rs = cursor.fetchall()

在这里我已经得到了异常:“(0,'没有结果集')”

如何防止这个异常,检查结果集是否为空?

【问题讨论】:

  • 这是什么数据库?我不希望这里出现异常,而是 .fetchall() 返回一个空列表。
  • 返回 Django 2.1SQLite 的空列表

标签: python resultset python-db-api


【解决方案1】:

我的功能对我有好处

option = cursor.execute("SELECT value FROM options WHERE key = '{}'".format(key))
    if option.fetchone() is not None:
        return cursor.execute("SELECT value FROM options WHERE key = '{}'".format(key)).fetchone()

【讨论】:

  • 1. 使用.format() 或其他通用的字符串替换方式将参数传递给SQL 查询是一种非常糟糕的做法(SQL 注入!)。请使用参数化 SQL 查询,例如 Piney 在此处的回答:stackoverflow.com/a/49580560/320437 --- 2. 可能值得检查运行不同的查询而不是第一个查询是否更有效.我可以想象例如使用COUNT()FIRST_VALUE()
  • 当我使用代码时出现此错误sqlite3.ProgrammingError: Incorrect number of bindings supplied. The current statement uses 1, and there are 9 supplied.
【解决方案2】:

当我需要进行多个 sql 查询时,我遇到了类似的问题。 问题是某些查询没有返回结果,我想打印该结果。还有一个错误。如前所述,有几种解决方案。

if cursor.description is None:
    # No recordset for INSERT, UPDATE, CREATE, etc
    pass
else:
    # Recordset for SELECT

还有:

exist = cursor.fetchone()
if exist is None:
  ... # does not exist
else:
  ... # exists

其中一个解决方案是:

tryexcept 块可让您处理 error/exceptionsfinally 块允许您执行代码,而不管tryexcept 块的结果如何。 所以使用它可以解决提出的问题。

s = """ set current query acceleration = enable;
        set current GET_ACCEL_ARCHIVE = yes;
        SELECT * FROM TABLE_NAME;"""

query_sqls = [i.strip() + ";" for i in filter(None, s.split(';'))]
for sql in query_sqls:
    print(f"Executing SQL statements ====> {sql} <=====")
    cursor.execute(sql)
    print(f"SQL ====> {sql} <===== was executed successfully")
    try:
        print("\n****************** RESULT ***********************")
        for result in cursor.fetchall():
            print(result)
        print("****************** END RESULT ***********************\n")
    except Exception as e:
        print(f"SQL: ====> {sql} <==== doesn't have output!\n")
        # print(str(e))

输出:

Executing SQL statements ====> set current query acceleration = enable; <=====
SQL: ====> set current query acceleration = enable; <==== doesn't have output!

Executing SQL statements ====> set current GET_ACCEL_ARCHIVE = yes; <=====
SQL: ====> set current GET_ACCEL_ARCHIVE = yes; <==== doesn't have output!

Executing SQL statements ====> SELECT * FROM TABLE_NAME; <=====

****************** RESULT ***********************

       ----------   DATA   ----------

****************** END RESULT ***********************

上面的示例仅提供了一个简单的用途,作为可以帮助您解决问题的想法。当然,你也应该注意其他的错误,比如查询的正确性等等。

【讨论】:

    【解决方案3】:

    作为参考,cursor.rowcount 只会返回 CREATEUPDATEDELETE 语句:

     |  rowcount
     |      This read-only attribute specifies the number of rows the last DML statement
     |      (INSERT, UPDATE, DELETE) affected.  This is set to -1 for SELECT statements.
    

    【讨论】:

      【解决方案4】:

      cursor.rowcount 通常会设置为 0。

      但是,如果您正在运行一个从不返回结果集的语句(例如没有RETURNINGINSERTSELECT ... INTO),那么您不需要调用.fetchall();此类语句不会有结果集。调用.execute() 足以运行语句。


      请注意,如果数据库适配器无法确定确切的受影响计数,则还允许数据库适配器将行计数设置为 -1。见PEP 249 Cursor.rowcount specification

      属性为-1,以防游标上没有.execute*()或者接口无法确定最后一次操作的行数。

      sqlite3 library 倾向于这样做。在所有这些情况下,如果您必须预先知道受影响的行数,请先在同一事务中执行 COUNT() 选择。

      【讨论】:

      • 在我的脚本中,我执行一个 sql 语句列表,测量它们的运行时间和点击次数。我无法事先知道语句是选择还是插入,有没有办法让我在每次查询执行后知道是否有结果集?非常感谢。
      • @TaoVenzke:使用try: results = cursor.fetchall() 然后用except 处理程序捕获异常?这种情况下并不是所有的数据库都会抛出异常,你这里用的是什么数据库?
      • 我正在使用 SAP HANA 数据库。我用 TRY 做到了,发现了一个异常。但我想在这种情况下避免例外。 cursor.rowcount 相当混乱:它为 select 语句返回 -1;对于插入语句,它返回 NOT 0,它返回的数字似乎是插入的记录数,但我真的可以相信它吗?
      • @user3665906:当您使用数据 query 语句(总是使用SELECT,但在执行存储过程时),您会得到一个空的结果集,然后cursor.rowcount 将是 0。对于数据操作语句(UPDATEINSERT),没有RETURNING 子句,您可以期望行数为-1,是的,但这取决于特定的数据库适配器,真的。
      • @xtian:只要坚持使用COUNT(),就可以得到一个实际的数字,保证。
      【解决方案5】:

      无论我尝试什么解决方案,我都遇到了 rowcount 总是返回 -1 的问题。

      我发现以下是检查空结果的好替代品。

      c.execute("SELECT * FROM users WHERE id=?", (id_num,))
      row = c.fetchone()
      if row == None:
         print("There are no results for this query")
      

      【讨论】:

      • 使用is None 比使用== None 更好。不是吗?
      【解决方案6】:

      你可以这样做:

      count = 0
      cnxn = pyodbc.connect("Driver={SQL Server Native Client 11.0};"
                            "Server=serverName;"
                            "Trusted_Connection=yes;")
      cursor = cnxn.cursor()
      cursor.execute(SQL query)
      for row in cursor:
          count = 1
          if true condition:
              print("True")
          else:
              print("False")
      if count == 0:
          print("No Result")
      

      谢谢:)

      【讨论】:

      • 发布答案时,请尝试解释为什么此答案可以解决问题,以及代码本身。
      【解决方案7】:

      如果您要连接到 postgres 数据库,则可以执行以下操作:

      result = cursor.execute(query)
      
      if result.returns_rows:
          # we got rows!
          return [{k:v for k,v in zip(result.keys(), r)} for r in result.rows]
      else:
          return None
      

      【讨论】:

        【解决方案8】:

        注意:这是针对 Python 中的 MySQLdb 模块。

        对于SELECT 语句,空记录集不应出现异常。 cursor.fetchall()Nonecursor.fetchone() 只是一个空列表 ([])。

        对于任何其他声明,例如INSERTUPDATE,不返回记录集,您既不能在光标上调用 fetchall() 也不能调用 fetchone()。否则,将引发异常。

        有一种方法可以区分上述两种类型的游标:

        def yield_data(cursor):
            while True:
                if cursor.description is None:
                    # No recordset for INSERT, UPDATE, CREATE, etc
                    pass
                else:
                    # Recordset for SELECT, yield data
                    yield cursor.fetchall()
                    # Or yield column names with
                    # yield [col[0] for col in cursor.description]
        
                # Go to the next recordset
                if not cursor.nextset():
                    # End of recordsets
                    return
        

        【讨论】:

          【解决方案9】:

          如果结果集为空,MySQLdb 不会引发异常。此外, cursor.execute() 函数将返回一个 long 值,它是获取的结果集中的行数。所以如果你想检查空结果,你的代码可以重写为

          rows_count = cursor.execute(query_sql)
          if rows_count > 0:
               rs = cursor.fetchall()
          else:
               // handle empty result set
          

          【讨论】:

          • 与 Oracle 配合得很好!
          猜你喜欢
          • 2014-04-13
          • 2014-04-13
          • 2018-12-13
          • 2018-03-24
          • 2010-10-17
          • 2020-04-09
          • 1970-01-01
          相关资源
          最近更新 更多