ZetCode

Python sqlite3.Cursor.execute 方法

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

这份综合指南探讨了 Python 的 sqlite3.Cursor.execute 方法,这是在 SQLite 数据库中执行 SQL 语句的主要方式。我们将涵盖基本用法、参数绑定、事务处理和实际示例。

基本定义

sqlite3.Cursor.execute 方法执行单个 SQL 语句。它将 SQL 查询作为其第一个参数,并将可选参数用于将值绑定到查询。

关键特性:它返回游标对象以进行链式调用,支持参数化查询以保证安全性,并且可以执行任何有效的 SQL 语句。该方法是所有数据库操作的核心。

基本 SQL 执行

这是 execute 最简单的用法,用于创建表和插入数据。该示例使用上下文管理器进行自动资源清理。

basic_execute.py
import sqlite3

with sqlite3.connect('example.db') as conn:
    with conn.cursor() as cursor:
        # Create table
        cursor.execute('''CREATE TABLE IF NOT EXISTS products
                        (id INTEGER PRIMARY KEY, name TEXT, price REAL)''')
        
        # Insert data
        cursor.execute("INSERT INTO products (name, price) VALUES (?, ?)", 
                      ('Laptop', 999.99))
        
        # Commit is automatic with context manager

此示例显示了基本工作流程:连接到数据库,创建游标,执行 SQL 语句。上下文管理器确保正确的资源清理。

INSERT 语句中的 ? 占位符演示了参数化查询,这可以防止 SQL 注入并处理正确的转义值。

参数绑定样式

execute 方法支持不同的参数绑定样式。此示例显示了所有三种支持的格式。

parameter_styles.py
import sqlite3

with sqlite3.connect('example.db') as conn:
    with conn.cursor() as cursor:
        # Question mark style (positional)
        cursor.execute("INSERT INTO products VALUES (?, ?, ?)", 
                      (2, 'Mouse', 19.99))
        
        # Named style
        cursor.execute("INSERT INTO products VALUES (:id, :name, :price)",
                      {'id': 3, 'name': 'Keyboard', 'price': 49.99})
        
        # Numbered style
        cursor.execute("INSERT INTO products VALUES (?1, ?2, ?3)",
                      (4, 'Monitor', 199.99))
        
        conn.commit()

SQLite 支持三种参数绑定样式:问号(位置)、命名和编号。每种方法都有优点,具体取决于用例。

命名参数在包含许多参数的复杂查询中尤其有用,因为它们使代码更具可读性和可维护性。

执行多个语句

executescript 方法允许一次执行多个 SQL 语句。这对于模式初始化或批量操作非常有用。

executescript.py
import sqlite3

sql_script = """
BEGIN TRANSACTION;
CREATE TABLE IF NOT EXISTS customers (
    id INTEGER PRIMARY KEY,
    name TEXT NOT NULL,
    email TEXT UNIQUE
);
CREATE TABLE IF NOT EXISTS orders (
    id INTEGER PRIMARY KEY,
    customer_id INTEGER,
    amount REAL,
    FOREIGN KEY (customer_id) REFERENCES customers(id)
);
COMMIT;
"""

with sqlite3.connect('shop.db') as conn:
    with conn.cursor() as cursor:
        cursor.executescript(sql_script)

此示例在单个事务中创建包含两个相关表的完整数据库模式。 executescript 方法解析并执行整个脚本。

请注意,executescript 在执行之前提交任何挂起的事务,并在执行之后再次提交。它是设置脚本的理想选择。

执行许多语句

executemany 方法使用不同的参数有效地多次执行相同的 SQL 语句。这比单个 executes 执行批量插入要快得多。

executemany.py
import sqlite3

products = [
    (5, 'Headphones', 79.99),
    (6, 'Webcam', 59.99),
    (7, 'Microphone', 89.99),
    (8, 'Speaker', 129.99)
]

with sqlite3.connect('example.db') as conn:
    with conn.cursor() as cursor:
        cursor.executemany("INSERT INTO products VALUES (?, ?, ?)", products)
        print(f"Inserted {cursor.rowcount} rows")

此示例在单个高效操作中插入多行。 executemany 方法针对此模式进行了优化。

rowcount 属性返回上次操作影响的行数。 对于 executemany,它显示总受影响的行。

获取结果

执行 SELECT 语句后,可以使用各种方法获取结果。 此示例演示了不同的获取方法。

fetching_results.py
import sqlite3

with sqlite3.connect('example.db') as conn:
    with conn.cursor() as cursor:
        # Execute SELECT
        cursor.execute("SELECT * FROM products WHERE price > ?", (50,))
        
        # Fetch one row
        print("First product over $50:", cursor.fetchone())
        
        # Fetch next 2 rows
        print("Next two products:", cursor.fetchmany(2))
        
        # Fetch all remaining rows
        print("All remaining products:", cursor.fetchall())

该示例显示了三种获取方法:fetchone 用于单行,fetchmany 用于指定数量的行,以及 fetchall 用于所有剩余的行。

游标维护有关结果集的状态,因此后续的 fetch 调用会从上一个调用停止的位置继续。 这样可以有效地处理大型结果集。

使用行工厂

行工厂允许自定义从查询返回行的方式。 此示例演示如何按名称而不是位置访问列。

row_factory.py
import sqlite3

with sqlite3.connect('example.db') as conn:
    # Set row factory for named access
    conn.row_factory = sqlite3.Row
    
    with conn.cursor() as cursor:
        cursor.execute("SELECT name, price FROM products WHERE id = ?", (1,))
        product = cursor.fetchone()
        
        # Access columns by name
        print(f"{product['name']} costs ${product['price']:.2f}")
        
        # Can still access by index
        print(f"Same product: {product[0]} costs ${product[1]:.2f}")

sqlite3.Row 工厂提供基于索引和基于名称的列访问。 这使得代码更具可读性,更能适应模式更改。

Row 对象还支持其他有用的功能,例如字典样式的键访问、keys 方法以及用于调试的正确字符串表示。

错误处理

正确的错误处理对于健壮的数据库应用程序至关重要。 此示例演示了在执行期间处理常见的 SQLite 错误。

error_handling.py
import sqlite3

try:
    with sqlite3.connect('example.db') as conn:
        with conn.cursor() as cursor:
            # This will fail (duplicate primary key)
            cursor.execute("INSERT INTO products VALUES (1, 'Tablet', 299.99)")
            conn.commit()
except sqlite3.IntegrityError as e:
    print(f"Integrity error: {e}")
except sqlite3.DatabaseError as e:
    print(f"Database error: {e}")
except Exception as e:
    print(f"Unexpected error: {e}")

该示例显示了如何处理特定的 SQLite 错误,例如违反约束的 IntegrityError。 可以使用 DatabaseError 捕获更一般的错误。

始终适当地处理数据库异常 - 至少记录它们,并经常为可恢复的错误实现重试逻辑或用户通知。

最佳实践

资料来源

作者

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

列出所有 Python 教程