sqlite3 — 用于 SQLite 数据库的 DB-API 2.0 接口

源代码: Lib/sqlite3/

SQLite 是一个 C 语言库,它提供了一个轻量级的基于磁盘的数据库,不需要单独的服务器进程,并且允许使用非标准的 SQL 查询语言变体访问数据库。一些应用程序可以使用 SQLite 进行内部数据存储。也可以使用 SQLite 对应用程序进行原型设计,然后将代码移植到更大的数据库,如 PostgreSQL 或 Oracle。

sqlite3 模块由 Gerhard Häring 编写。它提供了一个符合 PEP 249 描述的 DB-API 2.0 规范的 SQL 接口,并且需要 SQLite 3.7.15 或更高版本。

本文档包含四个主要部分

  • 教程 教您如何使用 sqlite3 模块。

  • 参考 描述了此模块定义的类和函数。

  • 操作指南 详细介绍了如何处理特定任务。

  • 说明 提供了有关事务控制的深入背景知识。

另请参阅

https://www.sqlite.org

SQLite 网页;文档描述了所支持 SQL 方言的语法和可用数据类型。

https://w3schools.org.cn/sql/

用于学习 SQL 语法的教程、参考和示例。

PEP 249 - 数据库 API 规范 2.0

由 Marc-André Lemburg 编写的 PEP。

教程

在本教程中,您将使用基本的 sqlite3 功能创建一个 Monty Python 电影数据库。它假设您对数据库概念有基本的了解,包括 游标事务

首先,我们需要创建一个新的数据库并打开一个数据库连接,以便 sqlite3 可以使用它。调用 sqlite3.connect() 创建到当前工作目录中数据库 tutorial.db 的连接,如果该数据库不存在,则隐式创建它

import sqlite3
con = sqlite3.connect("tutorial.db")

返回的 Connection 对象 con 表示到磁盘上数据库的连接。

为了执行 SQL 语句并从 SQL 查询中获取结果,我们需要使用数据库游标。调用 con.cursor() 创建 Cursor

cur = con.cursor()

现在我们有了一个数据库连接和一个游标,我们可以创建一个名为 movie 的数据库表,其中包含标题、发行年份和评分的列。为了简单起见,我们可以在表声明中只使用列名——由于 SQLite 的 灵活类型 特性,指定数据类型是可选的。通过调用 cur.execute(...) 执行 CREATE TABLE 语句

cur.execute("CREATE TABLE movie(title, year, score)")

我们可以通过查询 SQLite 内置的 sqlite_master 表来验证新表是否已创建,该表现在应该包含 movie 表定义的条目(有关详细信息,请参阅 模式表)。通过调用 cur.execute(...) 执行该查询,将结果分配给 res,并调用 res.fetchone() 获取结果行

>>> res = cur.execute("SELECT name FROM sqlite_master")
>>> res.fetchone()
('movie',)

我们可以看到表已创建,因为查询返回一个包含表名的 tuple。如果我们查询 sqlite_master 中不存在的表 spamres.fetchone() 将返回 None

>>> res = cur.execute("SELECT name FROM sqlite_master WHERE name='spam'")
>>> res.fetchone() is None
True

现在,通过执行 INSERT 语句添加两行作为 SQL 字面量提供的数据,再次通过调用 cur.execute(...)

cur.execute("""
    INSERT INTO movie VALUES
        ('Monty Python and the Holy Grail', 1975, 8.2),
        ('And Now for Something Completely Different', 1971, 7.5)
""")

INSERT 语句隐式打开一个事务,在将更改保存到数据库之前需要提交该事务(有关详细信息,请参阅 事务控制)。在连接对象上调用 con.commit() 以提交事务

con.commit()

我们可以通过执行 SELECT 查询来验证数据是否已正确插入。使用现在熟悉的 cur.execute(...) 将结果分配给 res,并调用 res.fetchall() 返回所有结果行

>>> res = cur.execute("SELECT score FROM movie")
>>> res.fetchall()
[(8.2,), (7.5,)]

结果是一个包含两个 tuplelist,每行一个,每个都包含该行的 score 值。

现在,通过调用 cur.executemany(...) 插入另外三行

data = [
    ("Monty Python Live at the Hollywood Bowl", 1982, 7.9),
    ("Monty Python's The Meaning of Life", 1983, 7.5),
    ("Monty Python's Life of Brian", 1979, 8.0),
]
cur.executemany("INSERT INTO movie VALUES(?, ?, ?)", data)
con.commit()  # Remember to commit the transaction after executing INSERT.

请注意,? 占位符用于将 data 绑定到查询。始终使用占位符而不是 字符串格式化 将 Python 值绑定到 SQL 语句,以避免 SQL 注入攻击(有关详细信息,请参阅 如何使用占位符绑定 SQL 查询中的值)。

我们可以通过执行 SELECT 查询来验证新行是否已插入,这次迭代查询的结果

>>> for row in cur.execute("SELECT year, title FROM movie ORDER BY year"):
...     print(row)
(1971, 'And Now for Something Completely Different')
(1975, 'Monty Python and the Holy Grail')
(1979, "Monty Python's Life of Brian")
(1982, 'Monty Python Live at the Hollywood Bowl')
(1983, "Monty Python's The Meaning of Life")

每一行都是一个包含 (year, title) 的两项 tuple,与查询中选择的列相匹配。

最后,通过调用 con.close() 关闭现有连接,打开一个新连接,创建一个新游标,然后查询数据库,以验证数据库是否已写入磁盘

>>> con.close()
>>> new_con = sqlite3.connect("tutorial.db")
>>> new_cur = new_con.cursor()
>>> res = new_cur.execute("SELECT title, year FROM movie ORDER BY score DESC")
>>> title, year = res.fetchone()
>>> print(f'The highest scoring Monty Python movie is {title!r}, released in {year}')
The highest scoring Monty Python movie is 'Monty Python and the Holy Grail', released in 1975
>>> new_con.close()

您现在已经使用 sqlite3 模块创建了一个 SQLite 数据库,并在其中插入了数据并以多种方式从中检索了值。

参考

模块函数

sqlite3.connect(database, timeout=5.0, detect_types=0, isolation_level='DEFERRED', check_same_thread=True, factory=sqlite3.Connection, cached_statements=128, uri=False, *, autocommit=sqlite3.LEGACY_TRANSACTION_CONTROL)

打开到 SQLite 数据库的连接。

参数:
  • database (类路径对象) – 要打开的数据库文件的路径。您可以传递 ":memory:" 来创建一个仅存在于内存中的 SQLite 数据库,并打开到该数据库的连接。

  • timeout (float) – 当表被锁定时,连接在引发 OperationalError 之前应等待的秒数。如果另一个连接打开一个事务来修改表,则该表将被锁定,直到事务提交。默认为 5 秒。

  • detect_types (int) – 控制是否以及如何查找 SQLite 本身不支持 的数据类型以将其转换为 Python 类型,使用在 register_converter() 中注册的转换器。将其设置为 PARSE_DECLTYPESPARSE_COLNAMES 的任意组合(使用 |,按位或)以启用此功能。如果同时设置了这两个标志,则列名优先于声明的类型。即使设置了 detect_types 参数,也无法检测生成字段(例如 max(data))的类型;将返回 str。默认情况下(0),类型检测被禁用。

  • isolation_level (str | None) – 控制旧版事务处理行为。有关更多信息,请参阅 Connection.isolation_level通过 isolation_level 属性进行事务控制。可以是 "DEFERRED"(默认值)、"EXCLUSIVE""IMMEDIATE";或者 None 以禁用隐式打开事务。除非将 Connection.autocommit 设置为 LEGACY_TRANSACTION_CONTROL(默认值),否则无效。

  • check_same_thread (bool) – 如果为 True(默认值),则如果数据库连接由创建它的线程以外的线程使用,则会引发 ProgrammingError。如果为 False,则可以在多个线程中访问连接;用户可能需要序列化写操作以避免数据损坏。有关更多信息,请参阅 threadsafety

  • factory (Connection) – 用于创建连接的 Connection 的自定义子类,如果不是默认的 Connection 类。

  • cached_statements (int) – sqlite3 应为此连接内部缓存的语句数,以避免解析开销。默认情况下,为 128 个语句。

  • uri (bool) – 如果设置为 True,则 database 将被解释为带有文件路径和可选查询字符串的 URI。方案部分必须"file:",并且路径可以是相对的或绝对的。查询字符串允许将参数传递给 SQLite,从而启用各种 如何使用 SQLite URI

  • autocommit (bool) – 控制 PEP 249 事务处理行为。有关更多信息,请参阅 Connection.autocommit通过 autocommit 属性控制事务autocommit 当前默认为 LEGACY_TRANSACTION_CONTROL。默认值将在未来的 Python 版本中更改为 False

返回类型:

连接

引发带有参数 database审计事件 sqlite3.connect

引发带有参数 connection_handle审计事件 sqlite3.connect/handle

版本 3.4 中的变化: 添加了 uri 参数。

版本 3.7 中的变化: database 现在也可以是 类路径对象,而不仅仅是字符串。

版本 3.10 中的变化: 添加了 sqlite3.connect/handle 审计事件。

版本 3.12 中的变化: 添加了 autocommit 参数。

sqlite3.complete_statement(statement)

如果字符串 statement 似乎包含一个或多个完整的 SQL 语句,则返回 True。除了检查没有未闭合的字符串字面量并且语句以分号结尾之外,不执行任何语法验证或解析。

例如

>>> sqlite3.complete_statement("SELECT foo FROM bar;")
True
>>> sqlite3.complete_statement("SELECT foo")
False

此函数在命令行输入期间可能很有用,用于确定输入的文本是否似乎形成了完整的 SQL 语句,或者在调用 execute() 之前是否需要其他输入。

有关实际使用,请参阅 Lib/sqlite3/__main__.py 中的 runsource()

sqlite3.enable_callback_tracebacks(flag, /)

启用或禁用回调回溯。默认情况下,您不会在用户定义的函数、聚合、转换器、授权器回调等中获得任何回溯。如果您想调试它们,可以使用设置为 Trueflag 调用此函数。之后,您将在 sys.stderr 上收到来自回调的回溯。使用 False 再次禁用该功能。

注意

用户定义函数回调中的错误记录为不可引发异常。使用 不可引发 钩子 处理程序 来内省失败的回调。

sqlite3.register_adapter(type, adapter, /)

注册一个 adapter 可调用对象,以将 Python 类型 type 适配为 SQLite 类型。适配器使用类型为 type 的 Python 对象作为其唯一参数进行调用,并且必须返回 SQLite 本身理解的类型 的值。

sqlite3.register_converter(typename, converter, /)

注册 converter 可调用对象,以将类型为 typename 的 SQLite 对象转换为特定类型的 Python 对象。转换器针对类型为 typename 的所有 SQLite 值调用;它传递一个 bytes 对象,并且应该返回所需 Python 类型的对象。有关类型检测工作原理的信息,请参阅 connect() 的参数 detect_types

注意:typename 和查询中类型的名称匹配时不区分大小写。

模块常量

sqlite3.LEGACY_TRANSACTION_CONTROL

autocommit 设置为此常量以选择旧式(Python 3.12 之前的)事务控制行为。有关更多信息,请参阅 通过 isolation_level 属性控制事务

sqlite3.PARSE_COLNAMES

将此标志值传递给 connect()detect_types 参数,以使用从查询列名解析的类型名称作为转换器字典键来查找转换器函数。类型名称必须用方括号 ([]) 括起来。

SELECT p as "p [point]" FROM test;  ! will look up converter "point"

可以使用 |(按位或)运算符将此标志与 PARSE_DECLTYPES 组合。

sqlite3.PARSE_DECLTYPES

将此标志值传递给 connect()detect_types 参数,以使用每列的声明类型查找转换器函数。类型在创建数据库表时声明。sqlite3 将使用声明类型的第一个单词作为转换器字典键来查找转换器函数。例如

CREATE TABLE test(
   i integer primary key,  ! will look up a converter named "integer"
   p point,                ! will look up a converter named "point"
   n number(10)            ! will look up a converter named "number"
 )

可以使用 |(按位或)运算符将此标志与 PARSE_COLNAMES 组合。

sqlite3.SQLITE_OK
sqlite3.SQLITE_DENY
sqlite3.SQLITE_IGNORE

传递给 Connection.set_authorizer()authorizer_callback 可调用对象 应该返回的标志,以指示是否

  • 允许访问 (SQLITE_OK),

  • SQL 语句应该中止并报错 (SQLITE_DENY)

  • 该列应被视为 NULL 值 (SQLITE_IGNORE)。

sqlite3.apilevel

表示所支持的 DB-API 级别的字符串常量。DB-API 所需。硬编码为 "2.0"

sqlite3.paramstyle

字符串常量,表示 sqlite3 模块期望的参数标记格式。DB-API 所需。硬编码为 "qmark"

注意

也支持 named DB-API 参数样式。

sqlite3.sqlite_version

运行时 SQLite 库的版本号,以 字符串 表示。

sqlite3.sqlite_version_info

运行时 SQLite 库的版本号,以 元组 表示,其中包含多个 整数

sqlite3.threadsafety

DB-API 2.0 所需的整数常量,表示 sqlite3 模块支持的线程安全级别。此属性根据编译底层 SQLite 库时使用的默认 线程模式 设置。SQLite 线程模式包括:

  1. **单线程**:在此模式下,所有互斥锁都被禁用,并且在多个线程中同时使用 SQLite 是不安全的。

  2. **多线程**:在此模式下,只要没有单个数据库连接同时在两个或多个线程中使用,就可以安全地在多个线程中使用 SQLite。

  3. **序列化**:在序列化模式下,可以在多个线程中安全地使用 SQLite,没有任何限制。

从 SQLite 线程模式到 DB-API 2.0 线程安全级别的映射如下:

SQLite 线程模式

线程安全

SQLITE_THREADSAFE

DB-API 2.0 含义

单线程

0

0

线程可能无法共享模块

多线程

1

2

线程可以共享模块,但不能共享连接

序列化

3

1

线程可以共享模块、连接和游标

在 3.11 版更改: 动态设置 threadsafety,而不是将其硬编码为 1

sqlite3.version

此模块的版本号,以 字符串 表示。这不是 SQLite 库的版本。

3.12 版后已弃用,将在 3.14 版中移除: 此常量用于反映 pysqlite 包的版本号,这是一个第三方库,用于将更改上游到 sqlite3。如今,它没有任何意义或实用价值。

sqlite3.version_info

此模块的版本号,以 元组 表示,其中包含多个 整数。这不是 SQLite 库的版本。

3.12 版后已弃用,将在 3.14 版中移除: 此常量用于反映 pysqlite 包的版本号,这是一个第三方库,用于将更改上游到 sqlite3。如今,它没有任何意义或实用价值。

sqlite3.SQLITE_DBCONFIG_DEFENSIVE
sqlite3.SQLITE_DBCONFIG_DQS_DDL
sqlite3.SQLITE_DBCONFIG_DQS_DML
sqlite3.SQLITE_DBCONFIG_ENABLE_FKEY
sqlite3.SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER
sqlite3.SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION
sqlite3.SQLITE_DBCONFIG_ENABLE_QPSG
sqlite3.SQLITE_DBCONFIG_ENABLE_TRIGGER
sqlite3.SQLITE_DBCONFIG_ENABLE_VIEW
sqlite3.SQLITE_DBCONFIG_LEGACY_ALTER_TABLE
sqlite3.SQLITE_DBCONFIG_LEGACY_FILE_FORMAT
sqlite3.SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE
sqlite3.SQLITE_DBCONFIG_RESET_DATABASE
sqlite3.SQLITE_DBCONFIG_TRIGGER_EQP
sqlite3.SQLITE_DBCONFIG_TRUSTED_SCHEMA
sqlite3.SQLITE_DBCONFIG_WRITABLE_SCHEMA

这些常量用于 Connection.setconfig()getconfig() 方法。

这些常量的可用性取决于编译 Python 时使用的 SQLite 版本。

3.12 版新增。

另请参阅

https://www.sqlite.org/c3ref/c_dbconfig_defensive.html

SQLite 文档:数据库连接配置选项

连接对象

class sqlite3.Connection

每个打开的 SQLite 数据库都由一个 Connection 对象表示,该对象使用 sqlite3.connect() 创建。它们的主要用途是创建 Cursor 对象和 事务控制

SQLite 数据库连接具有以下属性和方法:

cursor(factory=Cursor)

创建并返回一个 Cursor 对象。cursor 方法接受一个可选参数 *factory*。如果提供,则它必须是一个 可调用对象,返回 Cursor 或其子类的实例。

blobopen(table, column, row, /, *, readonly=False, name='main')

打开一个指向现有 BLOBBlob 句柄。

参数:
  • table (str) – blob 所在表的名称。

  • column (str) – blob 所在列的名称。

  • row (str) – blob 所在行的名称。

  • readonly (bool) – 如果 blob 应该以无写入权限打开,则设置为 True。默认为 False

  • name (str) – blob 所在数据库的名称。默认为 "main"

引发:

OperationalError – 尝试在 WITHOUT ROWID 表中打开 blob 时。

返回类型:

Blob

注意

不能使用 Blob 类更改 blob 大小。使用 SQL 函数 zeroblob 创建具有固定大小的 blob。

3.11 版新增。

commit()

将任何待处理的事务提交到数据库。如果 autocommitTrue,或者没有打开的事务,则此方法不执行任何操作。如果 autocommitFalse,则如果此方法提交了待处理的事务,则会隐式打开一个新事务。

rollback()

回滚到任何待处理事务的开始。如果 autocommitTrue,或者没有打开的事务,则此方法不执行任何操作。如果 autocommitFalse,则如果此方法回滚了待处理的事务,则会隐式打开一个新事务。

close()

关闭数据库连接。如果 autocommitFalse,则任何待处理的事务都将隐式回滚。如果 autocommitTrueLEGACY_TRANSACTION_CONTROL,则不执行隐式事务控制。请确保在关闭之前 commit(),以避免丢失待处理的更改。

execute(sql, parameters=(), /)

创建一个新的 Cursor 对象,并使用给定的 *sql* 和 *parameters* 对其调用 execute()。返回新的游标对象。

executemany(sql, parameters, /)

创建一个新的 Cursor 对象,并使用给定的 *sql* 和 *parameters* 对其调用 executemany()。返回新的游标对象。

executescript(sql_script, /)

创建一个新的 Cursor 对象,并使用给定的 *sql_script* 对其调用 executescript()。返回新的游标对象。

create_function(name, narg, func, *, deterministic=False)

创建或删除用户定义的 SQL 函数。

参数:
  • name (str) – SQL 函数的名称。

  • narg (int) – SQL 函数可以接受的参数数量。如果为 -1,则可以接受任意数量的参数。

  • func (回调 | None) – 调用 SQL 函数时调用的 可调用对象。可调用对象必须返回 SQLite 本地支持的类型。设置为 None 可删除现有的 SQL 函数。

  • deterministic (bool) – 如果为 True,则创建的 SQL 函数将标记为 确定性,这允许 SQLite 执行其他优化。

引发:

NotSupportedError – 如果在低于 3.8.3 版本的 SQLite 中使用 deterministic 参数,则会引发此错误。

在 3.8 版更改: 添加了 deterministic 参数。

示例

>>> import hashlib
>>> def md5sum(t):
...     return hashlib.md5(t).hexdigest()
>>> con = sqlite3.connect(":memory:")
>>> con.create_function("md5", 1, md5sum)
>>> for row in con.execute("SELECT md5(?)", (b"foo",)):
...     print(row)
('acbd18db4cc2f85cedef654fccc4a4d8',)
>>> con.close()
create_aggregate(name, n_arg, aggregate_class)

创建或删除用户定义的 SQL 聚合函数。

参数:
  • name (str) – SQL 聚合函数的名称。

  • n_arg (int) – SQL 聚合函数可以接受的参数数量。如果为 -1,则可以接受任意数量的参数。

  • aggregate_class ( | None) –

    类必须实现以下方法

    step() 方法必须接受的参数数量由 n_arg 控制。

    设置为 None 可删除现有的 SQL 聚合函数。

示例

class MySum:
    def __init__(self):
        self.count = 0

    def step(self, value):
        self.count += value

    def finalize(self):
        return self.count

con = sqlite3.connect(":memory:")
con.create_aggregate("mysum", 1, MySum)
cur = con.execute("CREATE TABLE test(i)")
cur.execute("INSERT INTO test(i) VALUES(1)")
cur.execute("INSERT INTO test(i) VALUES(2)")
cur.execute("SELECT mysum(i) FROM test")
print(cur.fetchone()[0])

con.close()
create_window_function(name, num_params, aggregate_class, /)

创建或删除用户定义的聚合窗口函数。

参数:
  • name (str) – 要创建或删除的 SQL 聚合窗口函数的名称。

  • num_params (int) – SQL 聚合窗口函数可以接受的参数数量。如果为 -1,则可以接受任意数量的参数。

  • aggregate_class ( | None) –

    必须实现以下方法的类

    • step():向当前窗口添加一行。

    • value():返回聚合的当前值。

    • inverse():从当前窗口中删除一行。

    • finalize():以 SQLite 本地支持的类型 返回聚合的最终结果。

    step()value() 方法必须接受的参数数量由 num_params 控制。

    设置为 None 可删除现有的 SQL 聚合窗口函数。

引发:

NotSupportedError – 如果在低于 3.25.0 版本的 SQLite 中使用此方法,则会引发此错误,因为该版本不支持聚合窗口函数。

3.11 版新增。

示例

# Example taken from https://www.sqlite.org/windowfunctions.html#udfwinfunc
class WindowSumInt:
    def __init__(self):
        self.count = 0

    def step(self, value):
        """Add a row to the current window."""
        self.count += value

    def value(self):
        """Return the current value of the aggregate."""
        return self.count

    def inverse(self, value):
        """Remove a row from the current window."""
        self.count -= value

    def finalize(self):
        """Return the final value of the aggregate.

        Any clean-up actions should be placed here.
        """
        return self.count


con = sqlite3.connect(":memory:")
cur = con.execute("CREATE TABLE test(x, y)")
values = [
    ("a", 4),
    ("b", 5),
    ("c", 3),
    ("d", 8),
    ("e", 1),
]
cur.executemany("INSERT INTO test VALUES(?, ?)", values)
con.create_window_function("sumint", 1, WindowSumInt)
cur.execute("""
    SELECT x, sumint(y) OVER (
        ORDER BY x ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING
    ) AS sum_y
    FROM test ORDER BY x
""")
print(cur.fetchall())
con.close()
create_collation(name, callable, /)

使用排序函数 callable 创建名为 name 的排序规则。callable 会传入两个 字符串 参数,并应返回一个 整数

  • 1 如果第一个参数的排序高于第二个参数

  • -1 如果第一个参数的排序低于第二个参数

  • 0 如果它们的排序相等

以下示例显示了反向排序规则

def collate_reverse(string1, string2):
    if string1 == string2:
        return 0
    elif string1 < string2:
        return 1
    else:
        return -1

con = sqlite3.connect(":memory:")
con.create_collation("reverse", collate_reverse)

cur = con.execute("CREATE TABLE test(x)")
cur.executemany("INSERT INTO test(x) VALUES(?)", [("a",), ("b",)])
cur.execute("SELECT x FROM test ORDER BY x COLLATE reverse")
for row in cur:
    print(row)
con.close()

通过将 callable 设置为 None 来删除排序函数。

在 3.11 版更改: 排序规则名称可以包含任何 Unicode 字符。此前,只允许使用 ASCII 字符。

interrupt()

从不同的线程调用此方法以中止可能正在连接上执行的任何查询。中止的查询将引发 OperationalError

set_authorizer(authorizer_callback)

注册 可调用对象 authorizer_callback,以便在每次尝试访问数据库中表的列时调用。回调函数应返回 SQLITE_OKSQLITE_DENYSQLITE_IGNORE 之一来指示底层 SQLite 库应如何处理对该列的访问。

回调函数的第一个参数表示要授权的操作类型。第二个和第三个参数将是参数或 None,具体取决于第一个参数。第四个参数是数据库的名称(“main”、“temp”等)(如果适用)。第五个参数是负责访问尝试的最内层触发器或视图的名称,如果此访问尝试直接来自输入 SQL 代码,则为 None

有关第一个参数的可能值以及第二个和第三个参数的含义(取决于第一个参数),请参阅 SQLite 文档。所有必要的常量都可以在 sqlite3 模块中找到。

传递 None 作为 authorizer_callback 将禁用授权器。

在 3.11 版更改: 添加了使用 None 禁用授权器的支持。

set_progress_handler(progress_handler, n)

注册 可调用对象 progress_handler,以便在 SQLite 虚拟机的每 n 条指令执行时调用。如果您希望在长时间运行的操作期间从 SQLite 中调用,例如更新 GUI,这将非常有用。

如果要清除任何先前安装的进度处理程序,请使用 progress_handlerNone 调用该方法。

从处理程序函数返回非零值将终止当前正在执行的查询,并导致其引发 DatabaseError 异常。

set_trace_callback(trace_callback)

注册 可调用对象 trace_callback,以便在 SQLite 后端实际执行的每个 SQL 语句时调用。

传递给回调函数的唯一参数是正在执行的语句(作为 str)。回调函数的返回值将被忽略。请注意,后端不仅运行传递给 Cursor.execute() 方法的语句。其他来源包括 sqlite3 模块的 事务管理 和当前数据库中定义的触发器的执行。

传递 None 作为 trace_callback 将禁用跟踪回调。

注意

跟踪回调中引发的异常不会传播。作为开发和调试辅助,请使用 enable_callback_tracebacks() 来启用从跟踪回调中引发的异常打印回溯。

3.3 版新增。

enable_load_extension(enabled, /)

如果 enabledTrue,则允许 SQLite 引擎从共享库加载 SQLite 扩展;否则,禁止加载 SQLite 扩展。SQLite 扩展可以定义新的函数、聚合或全新的虚拟表实现。一个著名的扩展是 SQLite 附带的全文搜索扩展。

注意

sqlite3 模块默认情况下不构建为支持可加载扩展,因为某些平台(特别是 macOS)的 SQLite 库在编译时没有此功能。要获得可加载扩展支持,您必须将 --enable-loadable-sqlite-extensions 选项传递给 configure

使用参数 connectionenabled 引发 审计事件 sqlite3.enable_load_extension

3.2 版新增。

3.10 版更改: 添加了 sqlite3.enable_load_extension 审计事件。

con.enable_load_extension(True)

# Load the fulltext search extension
con.execute("select load_extension('./fts3.so')")

# alternatively you can load the extension using an API call:
# con.load_extension("./fts3.so")

# disable extension loading again
con.enable_load_extension(False)

# example from SQLite wiki
con.execute("CREATE VIRTUAL TABLE recipe USING fts3(name, ingredients)")
con.executescript("""
    INSERT INTO recipe (name, ingredients) VALUES('broccoli stew', 'broccoli peppers cheese tomatoes');
    INSERT INTO recipe (name, ingredients) VALUES('pumpkin stew', 'pumpkin onions garlic celery');
    INSERT INTO recipe (name, ingredients) VALUES('broccoli pie', 'broccoli cheese onions flour');
    INSERT INTO recipe (name, ingredients) VALUES('pumpkin pie', 'pumpkin sugar flour butter');
    """)
for row in con.execute("SELECT rowid, name, ingredients FROM recipe WHERE name MATCH 'pie'"):
    print(row)
load_extension(path, /, *, entrypoint=None)

从共享库加载 SQLite 扩展。在调用此方法之前,请使用 enable_load_extension() 启用扩展加载。

参数:
  • path (str) – SQLite 扩展的路径。

  • entrypoint (str | None) – 入口点名称。如果为 None(默认值),SQLite 将使用它自己的入口点名称;有关详细信息,请参阅 SQLite 文档 加载扩展

使用参数 connectionpath 引发 审计事件 sqlite3.load_extension

3.2 版新增。

3.10 版更改: 添加了 sqlite3.load_extension 审计事件。

3.12 版更改: 添加了 entrypoint 参数。

iterdump()

返回一个 迭代器,以将数据库转储为 SQL 源代码。在保存内存数据库以供以后恢复时很有用。类似于 sqlite3 shell 中的 .dump 命令。

示例

# Convert file example.db to SQL dump file dump.sql
con = sqlite3.connect('example.db')
with open('dump.sql', 'w') as f:
    for line in con.iterdump():
        f.write('%s\n' % line)
con.close()
backup(target, *, pages=-1, progress=None, name='main', sleep=0.250)

创建 SQLite 数据库的备份。

即使其他客户端或同一连接正在并发访问数据库,此方法也能正常工作。

参数:
  • target (Connection) – 用于保存备份的数据库连接。

  • pages (int) – 一次复制的页数。如果等于或小于 0,则一次性复制整个数据库。默认为 -1

  • progress (回调 | None) – 如果设置为 可调用对象,则每次备份迭代都会使用三个整数参数调用它:最后一次迭代的 status(状态)、remaining(剩余)要复制的页数和 total(总)页数。默认为 None

  • name (str) – 要备份的数据库的名称。可以是 "main"(默认值),表示主数据库;"temp",表示临时数据库;或者使用 ATTACH DATABASE SQL 语句附加的自定义数据库的名称。

  • sleep (float) – 连续尝试备份剩余页面之间休眠的秒数。

示例 1,将现有数据库复制到另一个数据库

def progress(status, remaining, total):
    print(f'Copied {total-remaining} of {total} pages...')

src = sqlite3.connect('example.db')
dst = sqlite3.connect('backup.db')
with dst:
    src.backup(dst, pages=1, progress=progress)
dst.close()
src.close()

示例 2,将现有数据库复制到临时副本

src = sqlite3.connect('example.db')
dst = sqlite3.connect(':memory:')
src.backup(dst)
dst.close()
src.close()

3.7 版新增。

getlimit(category, /)

获取连接运行时限制。

参数:

category (int) – 要查询的 SQLite 限制类别

返回类型:

int

引发:

ProgrammingError – 如果底层 SQLite 库无法识别 category

示例,查询 Connection con 的 SQL 语句的最大长度(默认值为 1000000000)

>>> con.getlimit(sqlite3.SQLITE_LIMIT_SQL_LENGTH)
1000000000

3.11 版新增。

setlimit(category, limit, /)

设置连接运行时限制。尝试将限制增加到其硬上限以上时,会自动截断为硬上限。无论限制是否已更改,都会返回限制的先前值。

参数:
  • category (int) – 要设置的 SQLite 限制类别

  • limit (int) – 新限制的值。如果为负数,则当前限制保持不变。

返回类型:

int

引发:

ProgrammingError – 如果底层 SQLite 库无法识别 category

示例,将 Connection con 的附加数据库数量限制为 1(默认限制为 10)

>>> con.setlimit(sqlite3.SQLITE_LIMIT_ATTACHED, 1)
10
>>> con.getlimit(sqlite3.SQLITE_LIMIT_ATTACHED)
1

3.11 版新增。

getconfig(op, /)

查询布尔连接配置选项。

参数:

op (int) – SQLITE_DBCONFIG 代码

返回类型:

bool

3.12 版新增。

setconfig(op, enable=True, /)

设置布尔连接配置选项。

参数:
  • op (int) – SQLITE_DBCONFIG 代码

  • enable (bool) – 如果应启用配置选项,则为 True(默认值);如果应禁用,则为 False

3.12 版新增。

serialize(*, name='main')

将数据库序列化为 bytes 对象。对于普通的磁盘数据库文件,序列化只是磁盘文件的副本。对于内存数据库或“临时”数据库,序列化与将该数据库备份到磁盘时写入磁盘的字节序列相同。

参数:

name (str) – 要序列化的数据库名称。默认为 "main"

返回类型:

bytes

注意

仅当底层 SQLite 库具有序列化 API 时,此方法才可用。

3.11 版新增。

deserialize(data, /, *, name='main')

序列化 的数据库反序列化为 Connection。此方法会导致数据库连接断开与数据库 *name* 的连接,并根据 *data* 中包含的序列化将 *name* 重新打开为内存数据库。

参数:
  • data (bytes) – 序列化数据库。

  • name (str) – 要反序列化到的数据库名称。默认为 "main"

引发:

注意

仅当底层 SQLite 库具有反序列化 API 时,此方法才可用。

3.11 版新增。

autocommit

此属性控制符合 PEP 249 的事务行为。 autocommit 允许三个值

autocommit 更改为 False 将打开一个新事务,将其更改为 True 将提交任何挂起的事务。

有关更多详细信息,请参阅 通过 autocommit 属性进行事务控制

注意

除非 autocommitLEGACY_TRANSACTION_CONTROL,否则 isolation_level 属性无效。

3.12 版新增。

in_transaction

此只读属性对应于低级 SQLite 自动提交模式

如果事务处于活动状态(存在未提交的更改),则为 True,否则为 False

3.2 版新增。

isolation_level

控制 sqlite3旧版事务处理模式。如果设置为 None,则永远不会隐式打开事务。如果设置为 "DEFERRED""IMMEDIATE""EXCLUSIVE" 之一,对应于底层 SQLite 事务行为,则执行 隐式事务管理

如果未被 connect() 的 *isolation_level* 参数覆盖,则默认为 "",它是 "DEFERRED" 的别名。

注意

建议使用 autocommit 来控制事务处理,而不是使用 isolation_level。除非 autocommit 设置为 LEGACY_TRANSACTION_CONTROL(默认值),否则 isolation_level 无效。

row_factory

从此连接创建的 Cursor 对象的初始 row_factory。分配给此属性不会影响属于此连接的现有游标的 row_factory,只会影响新游标。默认情况下为 None,这意味着每行都作为 tuple 返回。

有关更多详细信息,请参阅 如何创建和使用行工厂

text_factory

一个接受 可调用对象bytes 参数并返回其文本表示形式。该可调用对象被调用用于具有 TEXT 数据类型的 SQLite 值。默认情况下,此属性设置为 str

有关更多详细信息,请参阅 如何处理非 UTF-8 文本编码

total_changes

返回自数据库连接打开以来已修改、插入或删除的数据库行总数。

游标对象

Cursor 对象表示一个 数据库游标,用于执行 SQL 语句并管理提取操作的上下文。游标是使用 Connection.cursor() 创建的,或者使用任何 连接快捷方法 创建的。

游标对象是 迭代器,这意味着如果您 execute() 一个 SELECT 查询,您可以简单地迭代游标以获取结果行

for row in cur.execute("SELECT t FROM data"):
    print(row)
class sqlite3.Cursor

Cursor 实例具有以下属性和方法。

execute(sql, parameters=(), /)

执行单个 SQL 语句,可以选择使用 占位符 绑定 Python 值。

参数:
引发:

ProgrammingError – 如果 sql 包含多个 SQL 语句。

如果 autocommitLEGACY_TRANSACTION_CONTROLisolation_level 不为 NonesqlINSERTUPDATEDELETEREPLACE 语句,并且没有打开的事务,则在执行 sql 之前会隐式打开一个事务。

从 3.12 版开始弃用,将在 3.14 版中删除: 如果使用 命名占位符 并且 parameters 是序列而不是 dict,则会发出 DeprecationWarning。从 Python 3.14 开始,将改为引发 ProgrammingError

使用 executescript() 执行多个 SQL 语句。

executemany(sql, parameters, /)

对于 parameters 中的每个项目,重复执行 参数化DML SQL 语句 sql

使用与 execute() 相同的隐式事务处理。

参数:
引发:

ProgrammingError – 如果 sql 包含多个 SQL 语句,或者不是 DML 语句。

示例

rows = [
    ("row1",),
    ("row2",),
]
# cur is an sqlite3.Cursor object
cur.executemany("INSERT INTO data VALUES(?)", rows)

注意

任何结果行都将被丢弃,包括带有 RETURNING 子句 的 DML 语句。

从 3.12 版开始弃用,将在 3.14 版中删除: 如果使用 命名占位符 并且 parameters 中的项目是序列而不是 dict,则会发出 DeprecationWarning。从 Python 3.14 开始,将改为引发 ProgrammingError

executescript(sql_script, /)

执行 sql_script 中的 SQL 语句。如果 autocommitLEGACY_TRANSACTION_CONTROL 并且存在挂起的事务,则首先执行隐式 COMMIT 语句。不执行其他隐式事务控制;任何事务控制都必须添加到 sql_script 中。

sql_script 必须是 string

示例

# cur is an sqlite3.Cursor object
cur.executescript("""
    BEGIN;
    CREATE TABLE person(firstname, lastname, age);
    CREATE TABLE book(title, author, published);
    CREATE TABLE publisher(name, address);
    COMMIT;
""")
fetchone()

如果 row_factoryNone,则将查询结果集中的下一行作为 tuple 返回。否则,将其传递给行工厂并返回其结果。如果没有更多可用数据,则返回 None

fetchmany(size=cursor.arraysize)

将查询结果的下一组行作为 list 返回。如果没有更多可用行,则返回空列表。

每次调用要获取的行数由 size 参数指定。如果未给出 size,则 arraysize 确定要获取的行数。如果可用行数少于 size,则返回尽可能多的可用行。

请注意,size 参数涉及性能方面的考虑。为了获得最佳性能,通常最好使用 arraysize 属性。如果使用 size 参数,则最好在从一次 fetchmany() 调用到下一次调用时保持相同的值。

fetchall()

将查询结果的所有(剩余)行作为 list 返回。如果没有可用行,则返回空列表。请注意,arraysize 属性可能会影响此操作的性能。

close()

立即关闭游标(而不是在调用 __del__ 时关闭)。

游标从此时起将无法使用;如果尝试使用游标执行任何操作,将引发 ProgrammingError 异常。

setinputsizes(sizes, /)

DB-API 所需。在 sqlite3 中不执行任何操作。

setoutputsize(size, column=None, /)

DB-API 所需。在 sqlite3 中不执行任何操作。

arraysize

读/写属性,控制 fetchmany() 返回的行数。默认值为 1,表示每次调用将获取一行。

connection

只读属性,提供属于游标的 SQLite 数据库 Connection。通过调用 con.cursor() 创建的 Cursor 对象将具有一个 connection 属性,该属性引用 con

>>> con = sqlite3.connect(":memory:")
>>> cur = con.cursor()
>>> cur.connection == con
True
>>> con.close()
description

只读属性,提供上次查询的列名。为了与 Python DB API 保持兼容,它为每一列返回一个 7 元组,其中每个元组的后六项均为 None

它也为没有任何匹配行的 SELECT 语句设置。

lastrowid

只读属性,提供最后插入行的行 ID。它仅在使用 execute() 方法成功执行 INSERTREPLACE 语句后更新。对于其他语句,在执行 executemany()executescript() 之后,或者如果插入失败,则 lastrowid 的值保持不变。lastrowid 的初始值为 None

注意

插入到 WITHOUT ROWID 表中的记录不会被记录。

在 3.6 版中更改: 添加了对 REPLACE 语句的支持。

rowcount

只读属性,提供 INSERTUPDATEDELETEREPLACE 语句修改的行数;对于其他语句(包括 CTE 查询),该属性为 -1。它仅在语句运行完成后由 execute()executemany() 方法更新。这意味着必须获取所有结果行才能更新 rowcount

row_factory

控制如何表示从 Cursor 获取的行。如果为 None,则行表示为 tuple。可以设置为包含的 sqlite3.Row;或者是一个 可调用对象,它接受两个参数,一个 Cursor 对象和一个行值的 tuple,并返回一个表示 SQLite 行的自定义对象。

默认为创建 CursorConnection.row_factory 的设置。分配给此属性不会影响父连接的 Connection.row_factory

有关更多详细信息,请参阅 如何创建和使用行工厂

行对象

class sqlite3.Row

Row 实例充当 Connection 对象的高度优化的 row_factory。它支持迭代、相等性测试、len() 以及按列名和索引进行的 映射 访问。

如果两个 Row 对象具有相同的列名和值,则它们相等。

有关更多详细信息,请参阅 如何创建和使用行工厂

keys()

字符串 形式返回列名 列表。在查询之后,它是 Cursor.description 中每个元组的第一个成员。

在 3.5 版更改: 添加了对切片的支持。

Blob 对象

class sqlite3.Blob

3.11 版新增。

Blob 实例是一个 类文件对象,可以在 SQLite BLOB 中读取和写入数据。调用 len(blob) 获取 blob 的大小(以字节为单位)。使用索引和 切片 直接访问 blob 数据。

Blob 用作 上下文管理器,以确保在使用后关闭 blob 句柄。

con = sqlite3.connect(":memory:")
con.execute("CREATE TABLE test(blob_col blob)")
con.execute("INSERT INTO test(blob_col) VALUES(zeroblob(13))")

# Write to our blob, using two write operations:
with con.blobopen("test", "blob_col", 1) as blob:
    blob.write(b"hello, ")
    blob.write(b"world.")
    # Modify the first and last bytes of our blob
    blob[0] = ord("H")
    blob[-1] = ord("!")

# Read the contents of our blob
with con.blobopen("test", "blob_col", 1) as blob:
    greeting = blob.read()

print(greeting)  # outputs "b'Hello, world!'"
con.close()
close()

关闭 blob。

此时起,blob 将无法使用。如果尝试使用 blob 进行任何进一步的操作,将引发 Error(或子类)异常。

read(length=-1, /)

从当前偏移位置开始读取 blob 中的 length 字节数据。如果到达 blob 的末尾,则返回到 EOF 的数据。如果未指定 length 或为负数,则 read() 将读取到 blob 的末尾。

write(data, /)

data 写入当前偏移位置的 blob。此函数不能更改 blob 长度。写入超出 blob 末尾将引发 ValueError

tell()

返回 blob 的当前访问位置。

seek(offset, origin=os.SEEK_SET, /)

将 blob 的当前访问位置设置为 offsetorigin 参数默认为 os.SEEK_SET(绝对 blob 定位)。origin 的其他值包括 os.SEEK_CUR(相对于当前位置查找)和 os.SEEK_END(相对于 blob 的末尾查找)。

PrepareProtocol 对象

class sqlite3.PrepareProtocol

PrepareProtocol 类型的唯一目的是充当 PEP 246 风格的适配协议,用于可以 自身适配 原生 SQLite 类型 的对象。

异常

异常层次结构由 DB-API 2.0 (PEP 249) 定义。

exception sqlite3.Warning

此异常当前不会由 sqlite3 模块引发,但可能会由使用 sqlite3 的应用程序引发,例如,如果用户定义的函数在插入时截断了数据。 WarningException 的子类。

异常 sqlite3.Error

此模块中其他异常的基类。使用此类可通过一个 except 语句捕获所有错误。 ErrorException 的子类。

如果异常源自 SQLite 库内部,则会将以下两个属性添加到异常中

sqlite_errorcode

SQLite API 中的数字错误代码

3.11 版新增。

sqlite_errorname

SQLite API 中数字错误代码的符号名称

3.11 版新增。

异常 sqlite3.InterfaceError

因误用低级 SQLite C API 而引发的异常。换句话说,如果引发此异常,则可能表示 sqlite3 模块中存在错误。 InterfaceErrorError 的子类。

异常 sqlite3.DatabaseError

因与数据库相关的错误而引发的异常。这用作几种数据库错误类型的基异常。它仅通过专门的子类隐式引发。 DatabaseErrorError 的子类。

异常 sqlite3.DataError

因处理的数据出现问题而引发的异常,例如数值超出范围以及字符串过长。 DataErrorDatabaseError 的子类。

异常 sqlite3.OperationalError

因与数据库操作相关的错误而引发的异常,并且不一定在程序员的控制之下。例如,找不到数据库路径,或者无法处理事务。 OperationalErrorDatabaseError 的子类。

异常 sqlite3.IntegrityError

当数据库的关系完整性受到影响时引发的异常,例如外键检查失败。它是 DatabaseError 的子类。

异常 sqlite3.InternalError

当 SQLite 遇到内部错误时引发的异常。如果引发此异常,则可能表示运行时 SQLite 库存在问题。 InternalErrorDatabaseError 的子类。

异常 sqlite3.ProgrammingError

sqlite3 API 编程错误而引发的异常,例如向查询提供错误数量的绑定,或者尝试对已关闭的 Connection 进行操作。 ProgrammingErrorDatabaseError 的子类。

异常 sqlite3.NotSupportedError

如果底层 SQLite 库不支持某个方法或数据库 API,则会引发此异常。例如,如果底层 SQLite 库不支持确定性函数,则在 create_function() 中将 *deterministic* 设置为 TrueNotSupportedErrorDatabaseError 的子类。

SQLite 和 Python 类型

SQLite 本身支持以下类型:NULLINTEGERREALTEXTBLOB

因此,以下 Python 类型可以毫无问题地发送到 SQLite

Python 类型

SQLite 类型

NULL

int

INTEGER

浮点数

REAL

字符串

TEXT

bytes

BLOB

默认情况下,SQLite 类型是这样转换为 Python 类型的

SQLite 类型

Python 类型

NULL

INTEGER

int

REAL

浮点数

TEXT

取决于 text_factory,默认为 str

BLOB

bytes

sqlite3 模块的类型系统可以通过两种方式扩展:您可以通过 对象适配器 将其他 Python 类型存储在 SQLite 数据库中,并且您可以让 sqlite3 模块通过 转换器 将 SQLite 类型转换为 Python 类型。

默认适配器和转换器(已弃用)

注意

默认适配器和转换器自 Python 3.12 起已弃用。请改用适配器和转换器配方并根据您的需要进行调整。

已弃用的默认适配器和转换器包括:

注意

默认的“时间戳”转换器会忽略数据库中的 UTC 偏移量,并始终返回一个单纯的 datetime.datetime 对象。要保留时间戳中的 UTC 偏移量,请禁用转换器,或使用 register_converter() 注册一个可识别偏移量的转换器。

自 3.12 版起弃用。

命令行界面

sqlite3 模块可以作为脚本调用,使用解释器的 -m 开关,以提供一个简单的 SQLite shell。参数签名如下:

python -m sqlite3 [-h] [-v] [filename] [sql]

输入 .quit 或 CTRL-D 退出 shell。

-h, --help

打印 CLI 帮助。

-v, --version

打印底层 SQLite 库版本。

3.12 版新增。

操作指南

如何在 SQL 查询中使用占位符绑定值

SQL 操作通常需要使用 Python 变量中的值。但是,请注意不要使用 Python 的字符串操作来组装查询,因为它们容易受到 SQL 注入攻击。例如,攻击者可以简单地关闭单引号并注入 OR TRUE 来选择所有行:

>>> # Never do this -- insecure!
>>> symbol = input()
' OR TRUE; --
>>> sql = "SELECT * FROM stocks WHERE symbol = '%s'" % symbol
>>> print(sql)
SELECT * FROM stocks WHERE symbol = '' OR TRUE; --'
>>> cur.execute(sql)

请改用 DB-API 的参数替换。要将变量插入查询字符串,请在字符串中使用占位符,并通过将实际值作为 元组 提供给游标的 execute() 方法的第二个参数来将它们替换到查询中。

SQL 语句可以使用两种占位符之一:问号(qmark 样式)或命名占位符(命名样式)。对于 qmark 样式,*参数* 必须是一个 序列,其长度必须与占位符的数量匹配,否则将引发 ProgrammingError。对于命名样式,*参数* 必须是 字典(或子类)的实例,其中必须包含所有命名参数的键;任何额外的项都将被忽略。以下是两种样式的示例:

con = sqlite3.connect(":memory:")
cur = con.execute("CREATE TABLE lang(name, first_appeared)")

# This is the named style used with executemany():
data = (
    {"name": "C", "year": 1972},
    {"name": "Fortran", "year": 1957},
    {"name": "Python", "year": 1991},
    {"name": "Go", "year": 2009},
)
cur.executemany("INSERT INTO lang VALUES(:name, :year)", data)

# This is the qmark style used in a SELECT query:
params = (1972,)
cur.execute("SELECT * FROM lang WHERE first_appeared = ?", params)
print(cur.fetchall())
con.close()

注意

PEP 249 数字占位符*不*受支持。如果使用,它们将被解释为命名占位符。

如何将自定义 Python 类型适配为 SQLite 值

SQLite 本身仅支持有限的数据类型集。要在 SQLite 数据库中存储自定义 Python 类型,请将它们*适配*为 SQLite 本身理解的 Python 类型 之一。

有两种方法可以将 Python 对象适配为 SQLite 类型:让对象自行适配,或使用*适配器可调用对象*。后者优先于前者。对于导出自定义类型的库,启用该类型以自行适配可能是有意义的。作为应用程序开发人员,通过注册自定义适配器函数直接控制可能更有意义。

如何编写可适配对象

假设我们有一个 Point 类,它表示笛卡尔坐标系中的一对坐标,xy。坐标对将存储为数据库中的文本字符串,使用分号分隔坐标。这可以通过添加一个 __conform__(self, protocol) 方法来实现,该方法返回适配后的值。传递给 *protocol* 的对象将是 PrepareProtocol 类型。

class Point:
    def __init__(self, x, y):
        self.x, self.y = x, y

    def __conform__(self, protocol):
        if protocol is sqlite3.PrepareProtocol:
            return f"{self.x};{self.y}"

con = sqlite3.connect(":memory:")
cur = con.cursor()

cur.execute("SELECT ?", (Point(4.0, -3.2),))
print(cur.fetchone()[0])
con.close()

如何注册适配器可调用对象

另一种可能性是创建一个函数,将 Python 对象转换为与 SQLite 兼容的类型。然后可以使用 register_adapter() 注册此函数。

class Point:
    def __init__(self, x, y):
        self.x, self.y = x, y

def adapt_point(point):
    return f"{point.x};{point.y}"

sqlite3.register_adapter(Point, adapt_point)

con = sqlite3.connect(":memory:")
cur = con.cursor()

cur.execute("SELECT ?", (Point(1.0, 2.5),))
print(cur.fetchone()[0])
con.close()

如何将 SQLite 值转换为自定义 Python 类型

编写适配器可以让您将*自定义 Python 类型*转换为*SQLite 值*。为了能够将*SQLite 值*转换为*自定义 Python 类型*,我们使用*转换器*。

让我们回到 Point 类。我们将以分号分隔的 x 和 y 坐标作为字符串存储在 SQLite 中。

首先,我们将定义一个转换器函数,它接受字符串作为参数并从中构造一个 Point 对象。

注意

转换器函数**始终**传递一个 字节 对象,无论底层的 SQLite 数据类型是什么。

def convert_point(s):
    x, y = map(float, s.split(b";"))
    return Point(x, y)

我们现在需要告诉 sqlite3 何时应该转换给定的 SQLite 值。这是在连接到数据库时完成的,使用 connect() 的 *detect_types* 参数。有三种选择:

  • 隐式:将 *detect_types* 设置为 PARSE_DECLTYPES

  • 显式:将 *detect_types* 设置为 PARSE_COLNAMES

  • 两者:将 *detect_types* 设置为 sqlite3.PARSE_DECLTYPES | sqlite3.PARSE_COLNAMES。列名优先于声明的类型。

以下示例说明了隐式和显式方法:

class Point:
    def __init__(self, x, y):
        self.x, self.y = x, y

    def __repr__(self):
        return f"Point({self.x}, {self.y})"

def adapt_point(point):
    return f"{point.x};{point.y}"

def convert_point(s):
    x, y = list(map(float, s.split(b";")))
    return Point(x, y)

# Register the adapter and converter
sqlite3.register_adapter(Point, adapt_point)
sqlite3.register_converter("point", convert_point)

# 1) Parse using declared types
p = Point(4.0, -3.2)
con = sqlite3.connect(":memory:", detect_types=sqlite3.PARSE_DECLTYPES)
cur = con.execute("CREATE TABLE test(p point)")

cur.execute("INSERT INTO test(p) VALUES(?)", (p,))
cur.execute("SELECT p FROM test")
print("with declared types:", cur.fetchone()[0])
cur.close()
con.close()

# 2) Parse using column names
con = sqlite3.connect(":memory:", detect_types=sqlite3.PARSE_COLNAMES)
cur = con.execute("CREATE TABLE test(p)")

cur.execute("INSERT INTO test(p) VALUES(?)", (p,))
cur.execute('SELECT p AS "p [point]" FROM test')
print("with column names:", cur.fetchone()[0])
cur.close()
con.close()

适配器和转换器配方

本节展示了常见适配器和转换器的配方。

import datetime
import sqlite3

def adapt_date_iso(val):
    """Adapt datetime.date to ISO 8601 date."""
    return val.isoformat()

def adapt_datetime_iso(val):
    """Adapt datetime.datetime to timezone-naive ISO 8601 date."""
    return val.isoformat()

def adapt_datetime_epoch(val):
    """Adapt datetime.datetime to Unix timestamp."""
    return int(val.timestamp())

sqlite3.register_adapter(datetime.date, adapt_date_iso)
sqlite3.register_adapter(datetime.datetime, adapt_datetime_iso)
sqlite3.register_adapter(datetime.datetime, adapt_datetime_epoch)

def convert_date(val):
    """Convert ISO 8601 date to datetime.date object."""
    return datetime.date.fromisoformat(val.decode())

def convert_datetime(val):
    """Convert ISO 8601 datetime to datetime.datetime object."""
    return datetime.datetime.fromisoformat(val.decode())

def convert_timestamp(val):
    """Convert Unix epoch timestamp to datetime.datetime object."""
    return datetime.datetime.fromtimestamp(int(val))

sqlite3.register_converter("date", convert_date)
sqlite3.register_converter("datetime", convert_datetime)
sqlite3.register_converter("timestamp", convert_timestamp)

如何使用连接快捷方法

通过使用 execute()executemany()executescript() 方法(属于 Connection 类),您的代码可以更加简洁,因为您不必显式创建(通常是多余的)Cursor 对象。相反,Cursor 对象是隐式创建的,并且这些快捷方法会返回游标对象。这样,您就可以执行 SELECT 语句并直接对其进行迭代,而只需对 Connection 对象进行一次调用。

# Create and fill the table.
con = sqlite3.connect(":memory:")
con.execute("CREATE TABLE lang(name, first_appeared)")
data = [
    ("C++", 1985),
    ("Objective-C", 1984),
]
con.executemany("INSERT INTO lang(name, first_appeared) VALUES(?, ?)", data)

# Print the table contents
for row in con.execute("SELECT name, first_appeared FROM lang"):
    print(row)

print("I just deleted", con.execute("DELETE FROM lang").rowcount, "rows")

# close() is not a shortcut method and it's not called automatically;
# the connection object should be closed manually
con.close()

如何使用连接上下文管理器

Connection 对象可以用作上下文管理器,在离开上下文管理器的主体时自动提交或回滚打开的事务。如果 with 语句的主体在没有异常的情况下完成,则提交事务。如果此提交失败,或者 with 语句的主体引发了未捕获的异常,则回滚事务。如果 autocommitFalse,则在提交或回滚后隐式打开一个新事务。

如果在离开 with 语句的主体时没有打开的事务,或者 autocommitTrue,则上下文管理器不执行任何操作。

注意

上下文管理器既不会隐式打开新事务,也不会关闭连接。如果您需要一个关闭的上下文管理器,请考虑使用 contextlib.closing()

con = sqlite3.connect(":memory:")
con.execute("CREATE TABLE lang(id INTEGER PRIMARY KEY, name VARCHAR UNIQUE)")

# Successful, con.commit() is called automatically afterwards
with con:
    con.execute("INSERT INTO lang(name) VALUES(?)", ("Python",))

# con.rollback() is called after the with block finishes with an exception,
# the exception is still raised and must be caught
try:
    with con:
        con.execute("INSERT INTO lang(name) VALUES(?)", ("Python",))
except sqlite3.IntegrityError:
    print("couldn't add Python twice")

# Connection object used as context manager only commits or rollbacks transactions,
# so the connection object should be closed manually
con.close()

如何使用 SQLite URI

一些有用的 URI 技巧包括:

  • 以只读模式打开数据库

>>> con = sqlite3.connect("file:tutorial.db?mode=ro", uri=True)
>>> con.execute("CREATE TABLE readonly(data)")
Traceback (most recent call last):
OperationalError: attempt to write a readonly database
  • 如果数据库文件不存在,则不隐式创建新文件;如果无法创建新文件,则会引发 OperationalError

>>> con = sqlite3.connect("file:nosuchdb.db?mode=rw", uri=True)
Traceback (most recent call last):
OperationalError: unable to open database file
  • 创建一个共享的命名内存数据库

db = "file:mem1?mode=memory&cache=shared"
con1 = sqlite3.connect(db, uri=True)
con2 = sqlite3.connect(db, uri=True)
with con1:
    con1.execute("CREATE TABLE shared(data)")
    con1.execute("INSERT INTO shared VALUES(28)")
res = con2.execute("SELECT data FROM shared")
assert res.fetchone() == (28,)

con1.close()
con2.close()

有关此功能的更多信息,包括参数列表,请参阅 SQLite URI 文档

如何创建和使用行工厂

默认情况下,sqlite3 使用 tuple 表示每一行。如果 tuple 不适合您的需求,您可以使用 sqlite3.Row 类或自定义 row_factory

虽然 row_factory 作为属性同时存在于 CursorConnection 上,但建议设置 Connection.row_factory,以便从连接创建的所有游标都使用相同的行工厂。

Row 提供对列的索引和不区分大小写的命名访问,与 tuple 相比,内存开销和性能影响最小。要将 Row 用作行工厂,请将其分配给 row_factory 属性

>>> con = sqlite3.connect(":memory:")
>>> con.row_factory = sqlite3.Row

查询现在返回 Row 对象

>>> res = con.execute("SELECT 'Earth' AS name, 6378 AS radius")
>>> row = res.fetchone()
>>> row.keys()
['name', 'radius']
>>> row[0]         # Access by index.
'Earth'
>>> row["name"]    # Access by name.
'Earth'
>>> row["RADIUS"]  # Column names are case-insensitive.
6378
>>> con.close()

注意

SELECT 语句中可以省略 FROM 子句,如上例所示。在这种情况下,SQLite 返回一行,其列由表达式定义,例如文字,并带有给定的别名 expr AS alias

您可以创建一个自定义 row_factory,将每一行作为 dict 返回,并将列名映射到值

def dict_factory(cursor, row):
    fields = [column[0] for column in cursor.description]
    return {key: value for key, value in zip(fields, row)}

使用它,查询现在返回 dict 而不是 tuple

>>> con = sqlite3.connect(":memory:")
>>> con.row_factory = dict_factory
>>> for row in con.execute("SELECT 1 AS a, 2 AS b"):
...     print(row)
{'a': 1, 'b': 2}
>>> con.close()

以下行工厂返回一个 命名元组

from collections import namedtuple

def namedtuple_factory(cursor, row):
    fields = [column[0] for column in cursor.description]
    cls = namedtuple("Row", fields)
    return cls._make(row)

namedtuple_factory() 可以按如下方式使用

>>> con = sqlite3.connect(":memory:")
>>> con.row_factory = namedtuple_factory
>>> cur = con.execute("SELECT 1 AS a, 2 AS b")
>>> row = cur.fetchone()
>>> row
Row(a=1, b=2)
>>> row[0]  # Indexed access.
1
>>> row.b   # Attribute access.
2
>>> con.close()

经过一些调整,可以调整上述方法以使用 dataclass 或任何其他自定义类,而不是 namedtuple

如何处理非 UTF-8 文本编码

默认情况下,sqlite3 使用 str 将 SQLite 值与 TEXT 数据类型进行适配。这适用于 UTF-8 编码的文本,但对于其他编码和无效的 UTF-8 可能会失败。您可以使用自定义 text_factory 来处理这种情况。

由于 SQLite 的灵活类型,因此遇到包含非 UTF-8 编码甚至任意数据的 TEXT 数据类型表列的情况并不少见。为了演示,我们假设有一个包含 ISO-8859-2(Latin-2)编码文本的数据库,例如一个捷克语-英语词典条目表。假设我们现在有一个连接到此数据库的 Connection 实例 con,我们可以使用此 text_factory 解码 Latin-2 编码的文本。

con.text_factory = lambda data: str(data, encoding="latin2")

对于存储在 TEXT 表列中的无效 UTF-8 或任意数据,可以使用以下技术,该技术借鉴自 Unicode 操作指南

con.text_factory = lambda data: str(data, errors="surrogateescape")

注意

sqlite3 模块 API 不支持包含代理项的字符串。

另请参阅

Unicode 操作指南

说明

事务控制

sqlite3 提供了多种方法来控制是否、何时以及如何打开和关闭数据库事务。建议使用 通过 autocommit 属性控制事务,而 通过 isolation_level 属性控制事务 保留了 Python 3.12 之前的行为。

通过 autocommit 属性控制事务

控制事务行为的推荐方法是通过 Connection.autocommit 属性,最好使用 connect() 的 *autocommit* 参数设置该属性。

建议将 *autocommit* 设置为 False,这意味着符合 PEP 249 的事务控制。这意味着

  • sqlite3 确保始终打开一个事务,因此 connect()Connection.commit()Connection.rollback() 将隐式打开一个新事务(对于后两者,在关闭挂起的事务之后立即打开)。sqlite3 在打开事务时使用 BEGIN DEFERRED 语句。

  • 应使用 commit() 显式提交事务。

  • 应使用 rollback() 显式回滚事务。

  • 如果数据库在 close() 时有挂起的更改,则会执行隐式回滚。

将 *autocommit* 设置为 True 以启用 SQLite 的自动提交模式。在此模式下,Connection.commit()Connection.rollback() 无效。请注意,SQLite 的自动提交模式与符合 PEP 249Connection.autocommit 属性不同;使用 Connection.in_transaction 查询低级 SQLite 自动提交模式。

将 *autocommit* 设置为 LEGACY_TRANSACTION_CONTROL 以将事务控制行为留给 Connection.isolation_level 属性。有关更多信息,请参阅 通过 isolation_level 属性控制事务

通过 isolation_level 属性控制事务

注意

控制事务的推荐方法是通过 autocommit 属性。请参阅 通过 autocommit 属性控制事务

如果 Connection.autocommit 设置为 LEGACY_TRANSACTION_CONTROL(默认值),则使用 Connection.isolation_level 属性控制事务行为。否则,isolation_level 无效。

如果连接属性 isolation_level 不为 None,则在 execute()executemany() 执行 INSERTUPDATEDELETEREPLACE 语句之前隐式打开新事务;对于其他语句,不执行隐式事务处理。使用 commit()rollback() 方法分别提交和回滚挂起的事务。您可以通过 isolation_level 属性选择底层 SQLite 事务行为,即 sqlite3 隐式执行的 BEGIN 语句的类型(如果有)。

如果 isolation_level 设置为 None,则根本不会隐式打开任何事务。这会使底层 SQLite 库处于自动提交模式,但也允许用户使用显式 SQL 语句执行自己的事务处理。可以使用 in_transaction 属性查询底层 SQLite 自动提交模式。

executescript() 方法会在执行给定的 SQL 脚本之前隐式提交任何待处理的事务,而不管 isolation_level 的值是多少。

3.6 版更改: sqlite3 过去会在 DDL 语句之前隐式提交打开的事务。现在不再是这样了。

3.12 版更改: 现在推荐使用 autocommit 属性来控制事务。