9.5 使用 SQL 结果集

当您使用 sql() 方法在会话上执行 SQL 操作时,将返回一个 SqlResult。迭代 SqlResult 与使用 CRUD 操作的结果相同。以下示例假设 users 表存在。

res = mySession.sql('SELECT name, age FROM users').execute()

row = res.fetch_one()

while row:
    print('Name: %s\n' % row[0])
    print(' Age: %s\n' % row.age)
    row = res.fetch_one()

SqlResult 与 CRUD 操作返回的结果的不同之处在于结果集和数据集的表示方式。SqlResult 将例如由 INSERT 生成的结果集和例如由 SELECT 生成的结果集组合在一起。与 CRUD 操作不同,对于 SqlResult,这两种类型之间没有区别。 SqlResult 实例导出用于访问数据以及检索最后插入的 ID 或受影响行数的方法。

使用 hasData() 方法了解 SqLResult 是数据集还是结果。当要编写的代码不知道 SqlResult 的来源时,该方法很有用。例如,在编写用于打印查询结果的通用应用程序函数或处理存储过程结果时,可能会出现这种情况。如果 hasData() 返回 true,则 SqlResult 来自可以返回行的 SELECT 或类似命令。

true 的返回值并不表示数据集中是否包含任何行。如果例如 fetchOne() 返回 NULLfetchAll() 返回空列表,则数据集可能为空。如果返回多个结果集,则任何结果集也可能为空。以下示例假设存储过程 my_proc 存在。

res = mySession.sql('CALL my_proc()').execute()

if res.has_data():

    row = res.fetch_one()
    if row:
        print('List of rows available for fetching.')
        while row:
            print(row)
            row = res.fetch_one()
    else:
        print('Empty list of rows.')
else:
    print('No row result.')

hasData() 指示 SqlResult 不是数据集时,调用 fetchOne()fetchAll() 都是错误的。

def print_result(res):
  if res.has_data():
    # SELECT
    columns = res.get_columns()
    record = res.fetch_one()

    while record:
      index = 0

      for column in columns:
        print("%s: %s \n" % (column.get_column_name(), record[index]))
        index = index + 1

      # Get the next record
      record = res.fetch_one()
  else:
    #INSERT, UPDATE, DELETE, ...
    print('Rows affected: %s' % res.get_affected_items_count())

print_result(mySession.sql('DELETE FROM users WHERE age < 30').execute())
print_result(mySession.sql('SELECT * FROM users WHERE age = 40').execute())

调用存储过程可能导致必须处理多个结果集作为单个执行的一部分。作为查询执行的结果,将返回一个 SqlResult 对象,该对象封装了第一个结果集。处理完结果集后,您可以调用 nextResult() 前进到下一个结果(如果有)。前进到下一个结果集后,它将替换先前加载的结果,然后该结果将变为不可用。

def print_result(res):
  if res.has_data():
    # SELECT
    columns = res.get_columns()
    record = res.fetch_one()

    while record:
      index = 0

      for column in columns:
        print("%s: %s \n" % (column.get_column_name(), record[index]))
        index = index + 1

      # Get the next record
      record = res.fetch_one()
  else:
    #INSERT, UPDATE, DELETE, ...
    print('Rows affected: %s' % res.get_affected_items_count())

res = mySession.sql('CALL my_proc()').execute()

# Prints each returned result
more = True
while more:
  print_result(res)
  more = res.next_result()

查询执行后,无法立即知道结果集的数量。查询结果可以流式传输到客户端或缓存在客户端。在流式传输或部分缓冲模式下,客户端无法判断查询是否发出多个结果集。