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 或更高版本。
本文档包含四个主要部分
另请参阅
- 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
中不存在的表 spam
,res.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,)]
结果是一个包含两个 tuple
的 list
,每行一个,每个都包含该行的 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_DECLTYPES
和PARSE_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, /)¶
启用或禁用回调回溯。默认情况下,您不会在用户定义的函数、聚合、转换器、授权器回调等中获得任何回溯。如果您想调试它们,可以使用设置为
True
的 flag 调用此函数。之后,您将在sys.stderr
上收到来自回调的回溯。使用False
再次禁用该功能。注意
用户定义函数回调中的错误记录为不可引发异常。使用
不可引发 钩子 处理程序
来内省失败的回调。
- sqlite3.register_adapter(type, adapter, /)¶
注册一个 adapter 可调用对象,以将 Python 类型 type 适配为 SQLite 类型。适配器使用类型为 type 的 Python 对象作为其唯一参数进行调用,并且必须返回 SQLite 本身理解的类型 的值。
模块常量¶
- 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.threadsafety¶
DB-API 2.0 所需的整数常量,表示
sqlite3
模块支持的线程安全级别。此属性根据编译底层 SQLite 库时使用的默认 线程模式 设置。SQLite 线程模式包括:**单线程**:在此模式下,所有互斥锁都被禁用,并且在多个线程中同时使用 SQLite 是不安全的。
**多线程**:在此模式下,只要没有单个数据库连接同时在两个或多个线程中使用,就可以安全地在多个线程中使用 SQLite。
**序列化**:在序列化模式下,可以在多个线程中安全地使用 SQLite,没有任何限制。
从 SQLite 线程模式到 DB-API 2.0 线程安全级别的映射如下:
SQLite 线程模式
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')¶
打开一个指向现有 BLOB 的
Blob
句柄。- 参数:
- 引发:
OperationalError – 尝试在
WITHOUT ROWID
表中打开 blob 时。- 返回类型:
注意
不能使用
Blob
类更改 blob 大小。使用 SQL 函数zeroblob
创建具有固定大小的 blob。3.11 版新增。
- commit()¶
将任何待处理的事务提交到数据库。如果
autocommit
为True
,或者没有打开的事务,则此方法不执行任何操作。如果autocommit
为False
,则如果此方法提交了待处理的事务,则会隐式打开一个新事务。
- rollback()¶
回滚到任何待处理事务的开始。如果
autocommit
为True
,或者没有打开的事务,则此方法不执行任何操作。如果autocommit
为False
,则如果此方法回滚了待处理的事务,则会隐式打开一个新事务。
- close()¶
关闭数据库连接。如果
autocommit
为False
,则任何待处理的事务都将隐式回滚。如果autocommit
为True
或LEGACY_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 函数。
- 参数:
- 引发:
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()
:向聚合中添加一行。finalize()
:以 SQLite 本地支持的类型 返回聚合的最终结果。
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_OK
、SQLITE_DENY
或SQLITE_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_handler 的
None
调用该方法。从处理程序函数返回非零值将终止当前正在执行的查询,并导致其引发
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, /)¶
如果 enabled 为
True
,则允许 SQLite 引擎从共享库加载 SQLite 扩展;否则,禁止加载 SQLite 扩展。SQLite 扩展可以定义新的函数、聚合或全新的虚拟表实现。一个著名的扩展是 SQLite 附带的全文搜索扩展。注意
sqlite3
模块默认情况下不构建为支持可加载扩展,因为某些平台(特别是 macOS)的 SQLite 库在编译时没有此功能。要获得可加载扩展支持,您必须将--enable-loadable-sqlite-extensions
选项传递给 configure。使用参数
connection
、enabled
引发 审计事件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()
启用扩展加载。- 参数:
使用参数
connection
、path
引发 审计事件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 限制类别。
- 返回类型:
- 引发:
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) – 新限制的值。如果为负数,则当前限制保持不变。
- 返回类型:
- 引发:
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 代码。
- 返回类型:
3.12 版新增。
- setconfig(op, enable=True, /)¶
设置布尔连接配置选项。
- 参数:
op (int) – SQLITE_DBCONFIG 代码。
enable (bool) – 如果应启用配置选项,则为
True
(默认值);如果应禁用,则为False
。
3.12 版新增。
- serialize(*, name='main')¶
将数据库序列化为
bytes
对象。对于普通的磁盘数据库文件,序列化只是磁盘文件的副本。对于内存数据库或“临时”数据库,序列化与将该数据库备份到磁盘时写入磁盘的字节序列相同。注意
仅当底层 SQLite 库具有序列化 API 时,此方法才可用。
3.11 版新增。
- deserialize(data, /, *, name='main')¶
将
序列化
的数据库反序列化为Connection
。此方法会导致数据库连接断开与数据库 *name* 的连接,并根据 *data* 中包含的序列化将 *name* 重新打开为内存数据库。- 参数:
- 引发:
OperationalError – 如果数据库连接当前正在进行读取事务或备份操作。
DatabaseError – 如果 *data* 不包含有效的 SQLite 数据库。
OverflowError – 如果
len(data)
大于2**63 - 1
。
注意
仅当底层 SQLite 库具有反序列化 API 时,此方法才可用。
3.11 版新增。
- autocommit¶
此属性控制符合 PEP 249 的事务行为。
autocommit
允许三个值False
:选择符合 PEP 249 的事务行为,这意味着sqlite3
确保始终打开事务。使用commit()
和rollback()
关闭事务。这是
autocommit
的建议值。True
:使用 SQLite 的 自动提交模式。commit()
和rollback()
在此模式下无效。LEGACY_TRANSACTION_CONTROL
:Python 3.12 之前(不符合 PEP 249)的事务控制。有关更多详细信息,请参阅isolation_level
。这是
autocommit
的当前默认值。
将
autocommit
更改为False
将打开一个新事务,将其更改为True
将提交任何挂起的事务。有关更多详细信息,请参阅 通过 autocommit 属性进行事务控制。
注意
除非
autocommit
为LEGACY_TRANSACTION_CONTROL
,否则isolation_level
属性无效。3.12 版新增。
- 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 值。
- 参数:
sql (str) – 单个 SQL 语句。
parameters (
dict
| 序列) – 要绑定到 sql 中占位符的 Python 值。如果使用命名占位符,则为dict
。如果使用未命名占位符,则为 序列。请参阅 如何在 SQL 查询中使用占位符绑定值。
- 引发:
ProgrammingError – 如果 sql 包含多个 SQL 语句。
如果
autocommit
为LEGACY_TRANSACTION_CONTROL
,isolation_level
不为None
,sql 是INSERT
、UPDATE
、DELETE
或REPLACE
语句,并且没有打开的事务,则在执行 sql 之前会隐式打开一个事务。从 3.12 版开始弃用,将在 3.14 版中删除: 如果使用 命名占位符 并且 parameters 是序列而不是
dict
,则会发出DeprecationWarning
。从 Python 3.14 开始,将改为引发ProgrammingError
。使用
executescript()
执行多个 SQL 语句。
- executemany(sql, parameters, /)¶
对于 parameters 中的每个项目,重复执行 参数化 的 DML SQL 语句 sql。
使用与
execute()
相同的隐式事务处理。- 参数:
sql (str) – 单个 SQL DML 语句。
parameters (可迭代对象) – 要与 sql 中的占位符绑定的 可迭代 参数。请参阅 如何在 SQL 查询中使用占位符绑定值。
- 引发:
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 语句。如果
autocommit
为LEGACY_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_factory
为None
,则将查询结果集中的下一行作为tuple
返回。否则,将其传递给行工厂并返回其结果。如果没有更多可用数据,则返回None
。
- fetchmany(size=cursor.arraysize)¶
将查询结果的下一组行作为
list
返回。如果没有更多可用行,则返回空列表。每次调用要获取的行数由 size 参数指定。如果未给出 size,则
arraysize
确定要获取的行数。如果可用行数少于 size,则返回尽可能多的可用行。请注意,size 参数涉及性能方面的考虑。为了获得最佳性能,通常最好使用 arraysize 属性。如果使用 size 参数,则最好在从一次
fetchmany()
调用到下一次调用时保持相同的值。
- 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()
方法成功执行INSERT
或REPLACE
语句后更新。对于其他语句,在执行executemany()
或executescript()
之后,或者如果插入失败,则lastrowid
的值保持不变。lastrowid
的初始值为None
。注意
插入到
WITHOUT ROWID
表中的记录不会被记录。在 3.6 版中更改: 添加了对
REPLACE
语句的支持。
- rowcount¶
只读属性,提供
INSERT
、UPDATE
、DELETE
和REPLACE
语句修改的行数;对于其他语句(包括 CTE 查询),该属性为-1
。它仅在语句运行完成后由execute()
和executemany()
方法更新。这意味着必须获取所有结果行才能更新rowcount
。
- row_factory¶
控制如何表示从
Cursor
获取的行。如果为None
,则行表示为tuple
。可以设置为包含的sqlite3.Row
;或者是一个 可调用对象,它接受两个参数,一个Cursor
对象和一个行值的tuple
,并返回一个表示 SQLite 行的自定义对象。默认为创建
Cursor
时Connection.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()
- 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 的当前访问位置设置为 offset。origin 参数默认为
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
的应用程序引发,例如,如果用户定义的函数在插入时截断了数据。Warning
是Exception
的子类。
- 异常 sqlite3.Error¶
此模块中其他异常的基类。使用此类可通过一个
except
语句捕获所有错误。Error
是Exception
的子类。如果异常源自 SQLite 库内部,则会将以下两个属性添加到异常中
- sqlite_errorcode¶
SQLite API 中的数字错误代码
3.11 版新增。
- sqlite_errorname¶
SQLite API 中数字错误代码的符号名称
3.11 版新增。
- 异常 sqlite3.InterfaceError¶
因误用低级 SQLite C API 而引发的异常。换句话说,如果引发此异常,则可能表示
sqlite3
模块中存在错误。InterfaceError
是Error
的子类。
- 异常 sqlite3.DatabaseError¶
因与数据库相关的错误而引发的异常。这用作几种数据库错误类型的基异常。它仅通过专门的子类隐式引发。
DatabaseError
是Error
的子类。
- 异常 sqlite3.DataError¶
因处理的数据出现问题而引发的异常,例如数值超出范围以及字符串过长。
DataError
是DatabaseError
的子类。
- 异常 sqlite3.OperationalError¶
因与数据库操作相关的错误而引发的异常,并且不一定在程序员的控制之下。例如,找不到数据库路径,或者无法处理事务。
OperationalError
是DatabaseError
的子类。
- 异常 sqlite3.IntegrityError¶
当数据库的关系完整性受到影响时引发的异常,例如外键检查失败。它是
DatabaseError
的子类。
- 异常 sqlite3.InternalError¶
当 SQLite 遇到内部错误时引发的异常。如果引发此异常,则可能表示运行时 SQLite 库存在问题。
InternalError
是DatabaseError
的子类。
- 异常 sqlite3.ProgrammingError¶
因
sqlite3
API 编程错误而引发的异常,例如向查询提供错误数量的绑定,或者尝试对已关闭的Connection
进行操作。ProgrammingError
是DatabaseError
的子类。
- 异常 sqlite3.NotSupportedError¶
如果底层 SQLite 库不支持某个方法或数据库 API,则会引发此异常。例如,如果底层 SQLite 库不支持确定性函数,则在
create_function()
中将 *deterministic* 设置为True
。NotSupportedError
是DatabaseError
的子类。
SQLite 和 Python 类型¶
SQLite 本身支持以下类型:NULL
、INTEGER
、REAL
、TEXT
、BLOB
。
因此,以下 Python 类型可以毫无问题地发送到 SQLite
Python 类型 |
SQLite 类型 |
---|---|
|
|
|
|
|
|
|
|
|
默认情况下,SQLite 类型是这样转换为 Python 类型的
SQLite 类型 |
Python 类型 |
---|---|
|
|
|
|
|
|
|
取决于 |
|
sqlite3
模块的类型系统可以通过两种方式扩展:您可以通过 对象适配器 将其他 Python 类型存储在 SQLite 数据库中,并且您可以让 sqlite3
模块通过 转换器 将 SQLite 类型转换为 Python 类型。
默认适配器和转换器(已弃用)¶
注意
默认适配器和转换器自 Python 3.12 起已弃用。请改用适配器和转换器配方并根据您的需要进行调整。
已弃用的默认适配器和转换器包括:
将
datetime.date
对象适配为字符串
(采用 ISO 8601 格式)的适配器。将
datetime.datetime
对象适配为字符串(采用 ISO 8601 格式)的适配器。将声明的“日期”类型转换为
datetime.date
对象的转换器。将声明的“时间戳”类型转换为
datetime.datetime
对象的转换器。小数部分将被截断为 6 位数字(微秒精度)。
注意
默认的“时间戳”转换器会忽略数据库中的 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
类,它表示笛卡尔坐标系中的一对坐标,x
和 y
。坐标对将存储为数据库中的文本字符串,使用分号分隔坐标。这可以通过添加一个 __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
语句的主体引发了未捕获的异常,则回滚事务。如果 autocommit
为 False
,则在提交或回滚后隐式打开一个新事务。
如果在离开 with
语句的主体时没有打开的事务,或者 autocommit
为 True
,则上下文管理器不执行任何操作。
注意
上下文管理器既不会隐式打开新事务,也不会关闭连接。如果您需要一个关闭的上下文管理器,请考虑使用 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
作为属性同时存在于 Cursor
和 Connection
上,但建议设置 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 不支持包含代理项的字符串。
另请参阅
说明¶
事务控制¶
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 249 的 Connection.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()
执行 INSERT
、UPDATE
、DELETE
或 REPLACE
语句之前隐式打开新事务;对于其他语句,不执行隐式事务处理。使用 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
属性来控制事务。