如何检查结果集是不是为空?

Posted

技术标签:

【中文标题】如何检查结果集是不是为空?【英文标题】: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 的空列表 【参考方案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 在此处的回答:***.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 配合得很好!

以上是关于如何检查结果集是不是为空?的主要内容,如果未能解决你的问题,请参考以下文章

如何检查结果集是不是有一行或更多?

servlet用HQL查询语句返回的结果集query.list()怎么进行判别是不是为空,或者说 结果集里有几组结果怎么查询

如何在不使用大型结果集的情况下检查一个字符串是不是是另一个字符串的子字符串?

oracle 存储过程中 如果用if语句判断一条查询语句的结果集是不是为空

简单检查 SELECT 查询空结果

Postgres检查jsonb数组是不是不包含值返回空结果集