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.15.2 或更高版本。

本文档包含四个主要部分

  • 教程 教导如何使用 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,每行一个,每个 tuple 包含该行的 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")

每一行都是一个包含两个元素的 tuple,格式为 (year, title),与查询中选择的列匹配。

最后,通过调用 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 之前应等待的秒数。如果另一个连接打开一个事务来修改一个表,该表将被锁定,直到事务被提交。默认为五秒。

  • detect_types (int) – 控制是否以及如何查找 SQLite 本身不支持 的数据类型,并使用通过 register_converter() 注册的转换器将其转换为 Python 类型。将其设置为 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。scheme 部分*必须*是 "file:",并且路径可以是相对的或绝对的。查询字符串允许将参数传递给 SQLite,从而启用各种 如何使用 SQLite URI

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

返回类型:

Connection

引发一个 审计事件 sqlite3.connect,参数为 database

引发一个 审计事件 sqlite3.connect/handle,参数为 connection_handle

3.4 版本更改: 添加了 uri 参数。

3.7 版本更改: database 现在也可以是 path-like object,而不仅限于字符串。

3.10 版本更改: 添加了 sqlite3.connect/handle 审计事件。

3.12 版本更改: 添加了 autocommit 参数。

3.13 版本更改: 参数 timeoutdetect_typesisolation_levelcheck_same_threadfactorycached_statementsuri 的位置用法已弃用。 它们将在 Python 3.15 中变为仅限关键字的参数。

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 再次禁用该功能。

注意

用户定义函数回调中的错误会作为无法引发的异常记录。 使用 unraisable hook handler 来内省失败的回调。

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 库的版本号,以 tuple 形式的 整数 表示。

sqlite3.threadsafety

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

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

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

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

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

SQLite 线程模式

threadsafety

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

此模块的版本号,以 tuple 形式的 整数 表示。这不是 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 对象和 事务控制

在 3.13 版本中更改: 如果在 Connection 对象被删除之前没有调用 close(),则会发出 ResourceWarning

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

cursor(factory=Cursor)

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

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

打开一个 Blob 句柄以访问现有的 BLOB

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

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

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

  • readonly (bool) – 如果应在没有写入权限的情况下打开 blob,则设置为 True。默认为 False

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

Raises:

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 对象,并使用给定的 sqlparameters 调用其上的 execute()。返回新的游标对象。

executemany(sql, parameters, /)

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

executescript(sql_script, /)

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

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

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

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

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

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

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

在 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()

在 3.13 版本中更改: namenargfunc 作为关键字参数传递已被弃用。这些参数将在 Python 3.15 中变为仅限位置参数。

create_aggregate(name, n_arg, aggregate_class)

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

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

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

  • aggregate_class (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()

在 3.13 版本中更改: namen_argaggregate_class 作为关键字参数传递已被弃用。这些参数将在 Python 3.15 中变为仅限位置参数。

create_window_function(name, num_params, aggregate_class, /)

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

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

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

  • aggregate_class (class | None) –

    一个必须实现以下方法的类

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

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

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

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

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

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

Raises:

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 禁用授权器的支持。

在 3.13 版本中更改: authorizer_callback 作为关键字参数传递已弃用。该参数将在 Python 3.15 中变为仅限位置参数。

set_progress_handler(progress_handler, n)

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

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

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

在 3.13 版本中更改: progress_handler 作为关键字参数传递已弃用。该参数将在 Python 3.15 中变为仅限位置参数。

set_trace_callback(trace_callback)

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

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

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

注意

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

在 3.3 版本中添加。

在 3.13 版本中更改: trace_callback 作为关键字参数传递已弃用。该参数将在 Python 3.15 中变为仅限位置参数。

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(*, filter=None)

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

参数:

filter (str | None) – 用于转储数据库对象的可选 LIKE 模式,例如 prefix_%。如果为 None (默认值),则将包括所有数据库对象。

示例

# 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()

在 3.13 版本中更改: 添加了 filter 参数。

backup(target, *, pages=-1, progress=None, name='main', sleep=0.250)

创建 SQLite 数据库的备份。

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

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

  • pages (int) – 每次复制的页数。如果等于或小于 0,则在单个步骤中复制整个数据库。默认为 -1

  • progress (回调 | None) – 如果设置为 可调用对象,则在每次备份迭代时都会使用三个整数参数调用它:上次迭代的状态、仍需复制的剩余页数和页数。默认为 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

Raises:

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

Raises:

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 对象。对于普通的磁盘数据库文件,序列化只是磁盘文件的副本。对于内存数据库或“temp”数据库,序列化是相同的字节序列,如果将该数据库备份到磁盘,则会写入磁盘。

参数:

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

返回类型:

bytes

注意

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

在 3.11 版本中添加。

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

序列化 数据库反序列化为 Connection。此方法导致数据库连接断开与数据库 _name_ 的连接,并基于 _data_ 中包含的序列化重新打开 _name_ 作为内存数据库。

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

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

Raises:

注意

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

在 3.11 版本中添加。

autocommit

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

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

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

注意

除非 autocommit 设置为 LEGACY_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 值。

参数:
Raises:

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() 相同的隐式事务处理。

参数:
Raises:

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 必须是一个 字符串

示例

# 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,则将下一个查询结果集行作为 元组 返回。否则,将其传递给行工厂并返回其结果。如果没有更多数据可用,则返回 None

fetchmany(size=cursor.arraysize)

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

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

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

fetchall()

将查询结果的所有(剩余)行作为 列表 返回。如果没有可用的行,则返回空列表。请注意,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,则行表示为 元组。 可以设置为包含的 sqlite3.Row; 或者设置为一个可调用对象,该对象接受两个参数,一个 Cursor 对象和行值的 tuple,并返回表示 SQLite 行的自定义对象。

默认值是创建 CursorConnection.row_factory 设置的值。 为此属性赋值不会影响父连接的 Connection.row_factory

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

行对象

class sqlite3.Row

Row 实例用作 row_factory 的高度优化实现,用于 Connection 对象。 它支持迭代、相等性测试、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 的子类。

exception sqlite3.Error

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

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

sqlite_errorcode

来自 SQLite API 的数字错误代码

在 3.11 版本中添加。

sqlite_errorname

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

在 3.11 版本中添加。

exception sqlite3.InterfaceError

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

exception sqlite3.DatabaseError

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

exception sqlite3.DataError

由于处理的数据出现问题(如数值超出范围和字符串过长)而引发的异常。 DataErrorDatabaseError 的子类。

exception sqlite3.OperationalError

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

exception sqlite3.IntegrityError

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

exception sqlite3.InternalError

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

exception sqlite3.ProgrammingError

sqlite3 API 编程出错时会引发此异常,例如,为查询提供的绑定数量不正确,或试图对已关闭的 Connection 进行操作。ProgrammingErrorDatabaseError 的子类。

exception sqlite3.NotSupportedError

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

SQLite 和 Python 类型

SQLite 本身支持以下类型:NULLINTEGERREALTEXTBLOB

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

Python 类型

SQLite 类型

None

NULL

int

int

float

REAL

str

TEXT

bytes

bytes

BLOB

SQLite 类型

Python 类型

NULL

None

int

int

REAL

float

TEXT

这是默认情况下 SQLite 类型转换为 Python 类型的方式

bytes

bytes

取决于 text_factory,默认为 str

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

注意

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

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

注意

用于将声明的 “timestamp” 类型转换为 datetime.datetime 对象的转换器。小数部分将被截断为 6 位数字(微秒精度)。

默认的 “timestamp” 转换器会忽略数据库中的 UTC 偏移量,并且始终返回一个朴素的 datetime.datetime 对象。若要保留时间戳中的 UTC 偏移量,可以禁用转换器,或者使用 register_converter() 注册一个感知偏移量的转换器。

自 3.12 版本起弃用。

命令行界面

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

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

键入 .quit 或 CTRL-D 以退出 shell。

-h, --help

打印 CLI 帮助。

-v, --version

在 3.12 版本中添加。

打印底层 SQLite 库的版本。

使用指南

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

>>> # 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)

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

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

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()

注意

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

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

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

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

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

如何编写可适配的对象

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()

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

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

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()

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

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

编写适配器允许您自定义 Python 类型转换为 SQLite 值。为了能够 SQLite 值转换为自定义 Python 类型,我们使用转换器

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

注意

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

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() 方法,你的代码可以写得更简洁,因为你不需要显式创建(通常是多余的) 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
>>> con.close()
  • 如果新数据库文件不存在,则不要隐式创建;如果无法创建新文件,则会引发 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()

以下行工厂返回一个 named tuple

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 来适配具有 TEXT 数据类型的 SQLite 值。这对于 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 HOWTO

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

注意

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

另请参阅

Unicode HOWTO

解释

事务控制

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() 方法分别提交和回滚待处理事务。您可以选择底层的SQLite 事务行为——也就是说,sqlite3 隐式执行的 BEGIN 语句的类型和执行方式——通过 isolation_level 属性。

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

无论 isolation_level 的值如何,executescript() 方法都会在执行给定的 SQL 脚本之前隐式提交任何待处理的事务。

在 3.6 版本中更改:sqlite3 曾经在 DDL 语句之前隐式提交打开的事务。现在不再这样了。

在 3.12 版本中更改:现在,控制事务的推荐方法是通过 autocommit 属性。