ZetCode

Python sqlite3.Row.keys 方法

上次修改时间:2025 年 4 月 15 日

本综合指南探讨了 Python 的 sqlite3.Row.keys 方法,该方法提供了对查询结果中列名的访问。我们将介绍基本用法、实际示例以及与数据库操作的集成。

基本定义

sqlite3.Row.keys 方法返回查询结果行中的列名列表。当使用 sqlite3.Row 作为连接的行工厂时,此方法可用。

主要特点:它提供与查询匹配的有序列名,允许命名访问行数据,并且适用于简单和复杂的查询。该方法对于动态 SQL 处理至关重要。

基本的 Row.keys 用法

这是使用 sqlite3.Row.keys 从查询结果中获取列名的最简单用法。

basic_keys.py
import sqlite3

with sqlite3.connect(':memory:') as conn:
    conn.row_factory = sqlite3.Row
    cursor = conn.cursor()
    
    cursor.execute('''CREATE TABLE users 
                     (id INTEGER PRIMARY KEY, name TEXT, email TEXT)''')
    cursor.execute("INSERT INTO users (name, email) VALUES ('Alice', 'alice@example.com')")
    
    cursor.execute("SELECT * FROM users")
    row = cursor.fetchone()
    
    print(row.keys())  # Output: ['id', 'name', 'email']

此示例创建一个带有简单表的内存数据库。在将 sqlite3.Row 设置为行工厂后,我们获取一行并打印其列名。

输出显示了列名,其顺序与它们在表中定义的顺序相同,展示了 keys 如何提供有关结果结构的元数据。

将 Keys 与动态查询一起使用

当处理事先不知道列名的动态查询时,keys 方法特别有用。

dynamic_query.py
import sqlite3

def print_query_results(conn, query):
    cursor = conn.cursor()
    cursor.execute(query)
    
    for row in cursor:
        print("Columns:", row.keys())
        for col in row.keys():
            print(f"{col}: {row[col]}")
        print()

with sqlite3.connect(':memory:') as conn:
    conn.row_factory = sqlite3.Row
    cursor = conn.cursor()
    
    cursor.execute('''CREATE TABLE products
                     (id INTEGER PRIMARY KEY, name TEXT, price REAL)''')
    cursor.executemany("INSERT INTO products (name, price) VALUES (?, ?)",
                      [('Laptop', 999.99), ('Phone', 699.99)])
    
    print_query_results(conn, "SELECT * FROM products")
    print_query_results(conn, "SELECT name, price FROM products WHERE price > 700")

此示例演示了一个可重用的函数,该函数打印查询结果及其列名。 keys 方法允许该函数处理任何查询,而无需事先了解其结构。

输出显示了不同查询的不同列集,证明了在处理动态 SQL 时这种方法的灵活性。

从行构建字典

我们可以将 keys 与字典推导式结合使用,将行转换为以列名作为键的字典。

row_to_dict.py
import sqlite3

with sqlite3.connect(':memory:') as conn:
    conn.row_factory = sqlite3.Row
    cursor = conn.cursor()
    
    cursor.execute('''CREATE TABLE employees
                     (id INTEGER, name TEXT, department TEXT, salary REAL)''')
    cursor.execute('''INSERT INTO employees VALUES
                     (1, 'John Smith', 'Engineering', 85000)''')
    
    cursor.execute("SELECT * FROM employees")
    row = cursor.fetchone()
    
    # Convert row to dictionary
    row_dict = {key: row[key] for key in row.keys()}
    print(row_dict)
    
    # Output: {'id': 1, 'name': 'John Smith', 'department': 'Engineering', 'salary': 85000.0}

此示例显示了如何将 sqlite3.Row 对象转换为常规字典。 keys 方法提供字典键。

当您需要序列化数据库行或将它们传递给期望字典而不是行对象的函数时,此技术非常有用。

验证列名

keys 方法可以帮助验证查询是否返回了预期的列,然后再处理数据。

validate_columns.py
import sqlite3

def validate_columns(row, expected_columns):
    actual_columns = row.keys()
    if set(expected_columns) != set(actual_columns):
        raise ValueError(f"Expected columns {expected_columns}, got {actual_columns}")

with sqlite3.connect(':memory:') as conn:
    conn.row_factory = sqlite3.Row
    cursor = conn.cursor()
    
    cursor.execute('''CREATE TABLE inventory
                     (item_id INTEGER, name TEXT, quantity INTEGER)''')
    cursor.execute('''INSERT INTO inventory VALUES
                     (101, 'Widget', 50)''')
    
    cursor.execute("SELECT item_id, name, quantity FROM inventory")
    row = cursor.fetchone()
    
    try:
        validate_columns(row, ['item_id', 'name', 'quantity'])
        print("Column validation passed")
    except ValueError as e:
        print("Column validation failed:", e)

此示例演示了一个验证函数,该函数检查行是否包含预期的列。 keys 方法提供用于比较的实际列名。

这种验证在查询结果必须符合特定模式或使用动态生成的 SQL 的应用程序中尤其有价值。

处理别名列

keys 方法反映 SQL 查询中使用的列别名,准确显示结果集中可用的名称。

column_aliases.py
import sqlite3

with sqlite3.connect(':memory:') as conn:
    conn.row_factory = sqlite3.Row
    cursor = conn.cursor()
    
    cursor.execute('''CREATE TABLE orders
                     (order_id INTEGER, customer TEXT, total REAL)''')
    cursor.execute('''INSERT INTO orders VALUES
                     (1001, 'Acme Corp', 1250.75)''')
    
    # Query with column aliases
    cursor.execute('''SELECT 
                     order_id AS id, 
                     customer AS client, 
                     total AS amount 
                     FROM orders''')
    row = cursor.fetchone()
    
    print("Column names:", row.keys())
    # Output: Column names: ['id', 'client', 'amount']
    
    # Access using aliases
    print(f"Order {row['id']} for {row['client']}: ${row['amount']}")

此示例显示了 SQL 查询中的列别名如何影响 keys 返回的名称。该方法提供别名,而不是表中原始的列名。

当处理复杂的查询,为了清晰或与应用程序代码兼容而重命名列时,理解这种行为非常重要。

使用连接的表

当查询具有连接的多个表时,keys 显示所有可用的列,包括来自不同表的重复名称。

joined_tables.py
import sqlite3

with sqlite3.connect(':memory:') as conn:
    conn.row_factory = sqlite3.Row
    cursor = conn.cursor()
    
    # Create two related tables
    cursor.execute('''CREATE TABLE departments
                     (id INTEGER, name TEXT)''')
    cursor.execute('''CREATE TABLE employees
                     (id INTEGER, name TEXT, dept_id INTEGER)''')
    
    # Add sample data
    cursor.execute("INSERT INTO departments VALUES (1, 'Engineering')")
    cursor.execute("INSERT INTO employees VALUES (101, 'Alice', 1)")
    
    # Query with join
    cursor.execute('''SELECT e.id AS emp_id, e.name AS emp_name,
                             d.id AS dept_id, d.name AS dept_name
                      FROM employees e
                      JOIN departments d ON e.dept_id = d.id''')
    
    row = cursor.fetchone()
    print("Column names:", row.keys())
    # Output: Column names: ['emp_id', 'emp_name', 'dept_id', 'dept_name']
    
    # Access specific columns
    print(f"{row['emp_name']} works in {row['dept_name']}")

此示例演示了 keys 如何处理来自连接表的列名。我们使用显式别名来避免结果集中的歧义。

该方法显示连接后所有可用的列,名称反映了我们的别名。这清楚地表明了哪些列来自哪些表。

高级:动态数据处理

为了获得最大的灵活性,我们可以使用 keys 处理查询结果,而无需事先了解表结构。

dynamic_processing.py
import sqlite3
from tabulate import tabulate

def execute_and_display(conn, query):
    cursor = conn.cursor()
    cursor.execute(query)
    
    if cursor.description is None:
        print("No results to display")
        return
    
    # Get all rows
    rows = cursor.fetchall()
    if not rows:
        print("No rows returned")
        return
    
    # Display as table
    headers = rows[0].keys()
    data = [[row[col] for col in headers] for row in rows]
    print(tabulate(data, headers=headers, tablefmt="grid"))

with sqlite3.connect(':memory:') as conn:
    conn.row_factory = sqlite3.Row
    cursor = conn.cursor()
    
    # Create sample data
    cursor.execute('''CREATE TABLE sales
                     (region TEXT, product TEXT, amount REAL, quarter INTEGER)''')
    cursor.executemany("INSERT INTO sales VALUES (?, ?, ?, ?)",
                      [('West', 'A', 1000, 1),
                       ('East', 'B', 1500, 1),
                       ('North', 'A', 800, 2)])
    
    # Display different queries
    execute_and_display(conn, "SELECT * FROM sales")
    execute_and_display(conn, "SELECT region, SUM(amount) AS total FROM sales GROUP BY region")

这个高级示例展示了一个通用函数,它可以执行任何查询并以格式化的表显示结果。 keys 方法自动提供列标题。

该函数处理不同的查询类型(简单的 selects,aggregates)而无需修改,展示了动态列名访问的强大功能。

最佳实践

资料来源

作者

我的名字是 Jan Bodnar,我是一位充满激情的程序员,拥有丰富的编程经验。 自 2007 年以来,我一直在撰写编程文章。 迄今为止,我已撰写了 1,400 多篇文章和 8 本电子书。 我拥有超过十年的编程教学经验。

列出所有 Python 教程