1. 简介

在 Odoo 中,执行 SQL 查询后可以使用 fetchall() 或 dictfetchall() 方法来获取查询结果。fetchall() 返回的是一个包含元组的列表,而 dictfetchall() 返回的是一个包含字典的列表。两者的主要区别在于数据访问的方式:fetchall() 通过索引访问数据,而 dictfetchall() 通过字段名称访问数据。

2. fetchall() 示例

首先,让我们看一下使用 fetchall() 的示例。

from odoo import models, api

class PartnerExample(models.Model):
    _inherit = 'res.partner'

    @api.model
    def get_partner_info(self):
        cr = self._cr  # 获取数据库游标
        cr.execute("""
            SELECT id, name, email
            FROM res_partner
            WHERE customer_rank > 0
        """)
        
        results = cr.fetchall()  # 获取查询结果

        # 处理结果
        for row in results:
            partner_id = row[0]  # 通过索引访问
            partner_name = row[1]
            partner_email = row[2]

            # 打印结果
            print(f"ID: {partner_id}, Name: {partner_name}, Email: {partner_email}")

        return results
运行结果:

假设 res_partner 表中的数据如下:

id

name

email

customer_rank

1

John Doe

john@example.com

1

2

Jane Smith

jane@example.com

2

执行该方法后,将输出:

ID: 1, Name: John Doe, Email: john@example.com
ID: 2, Name: Jane Smith, Email: jane@example.com
优点和缺点:
  • 优点
  • 更加简单直接,适合小规模数据处理。
  • 缺点
  • 如果列顺序改变,代码可能会出错。
  • 可读性较差,尤其是当列数较多时。

3. dictfetchall() 示例

看一下使用 dictfetchall() 的示例。

from odoo import models, api

class PartnerExample(models.Model):
    _inherit = 'res.partner'

    @api.model
    def get_partner_info(self):
        cr = self._cr  # 获取数据库游标
        cr.execute("""
            SELECT id, name, email
            FROM res_partner
            WHERE customer_rank > 0
        """)
        
        results = cr.dictfetchall()  # 使用dictfetchall获取结果

        # 处理结果
        for row in results:
            partner_id = row['id']  # 通过字段名称访问
            partner_name = row['name']
            partner_email = row['email']

            # 打印结果
            print(f"ID: {partner_id}, Name: {partner_name}, Email: {partner_email}")

        return results
运行结果:

数据表相同,执行该方法后输出与 fetchall() 示例相同:

ID: 1, Name: John Doe, Email: john@example.com
ID: 2, Name: Jane Smith, Email: jane@example.com
优点和缺点:
  • 优点
  • 使用字段名称访问数据,代码可读性更高。
  • 列顺序改变不会影响代码。
  • 缺点
  • 相比 fetchall(),可能略微增加了处理时间和内存占用。

4. 比较总结

  • fetchall():返回元组列表,数据访问通过索引完成。适合简单或性能要求较高的场景,但代码可读性较差且容易出错。
  • dictfetchall():返回字典列表,数据访问通过字段名称完成。代码更具可读性和维护性,适合处理复杂数据或长久维护的系统。

5. 实际应用场景

  • 使用 fetchall() 的场景:当你只处理少量列且数据结构很稳定时,可以选择 fetchall(),以稍微提升性能。
  • 使用 dictfetchall() 的场景:当你需要处理多列数据,并且需要代码的可读性和维护性,特别是在团队协作或长时间维护的项目中,dictfetchall() 是更好的选择。