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 或更新版本。
本文档包含四个主要部分
参见
- 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
表定义的条目(有关详细信息,请参阅 Schema Table)。通过调用 cur.execute(...)
执行该查询,将结果分配给 res
,然后调用 res.fetchone()
来获取结果行
>>> res = cur.execute("SELECT name FROM sqlite_master")
>>> res.fetchone()
('movie',)
我们可以看到表已经创建,因为查询返回一个包含表名的 元组
。如果我们查询 sqlite_master
以查找不存在的表 spam
,res.fetchone()
将返回 None
>>> res = cur.execute("SELECT name FROM sqlite_master WHERE name='spam'")
>>> res.fetchone() is None
True
现在,通过执行 INSERT
语句,再次通过调用 cur.execute(...)
,添加作为 SQL 字面量提供的两行数据
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
,每行一个,每个 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")
每行是一个包含两个项目的 元组
(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 (浮点数) – 当表被锁定后,连接应该等待多少秒才引发
OperationalError
。如果另一个连接打开事务以修改表,该表将被锁定直到事务提交。默认五秒。detect_types (整数) – 控制如何查找 SQLite 不原生支持 的数据类型,以使用
register_converter()
注册的转换器将其转换为 Python 类型。将其设置为PARSE_DECLTYPES
和PARSE_COLNAMES
的任意组合(使用|
,按位或)以启用此功能。如果同时设置了这两个标志,则列名优先于声明的类型。默认情况下 (0
),类型检测被禁用。isolation_level (字符串 | None) – 控制旧式事务处理行为。有关更多信息,请参阅
Connection.isolation_level
和 通过 isolation_level 属性进行事务控制。可以是"DEFERRED"
(默认)、"EXCLUSIVE"
或"IMMEDIATE"
;或者None
以禁用隐式打开事务。除非Connection.autocommit
设置为LEGACY_TRANSACTION_CONTROL
(默认值),否则无效。check_same_thread (布尔值) – 如果为
True
(默认),则如果数据库连接被创建它的线程以外的线程使用,将引发ProgrammingError
。如果为False
,则连接可以在多个线程中访问;用户可能需要序列化写入操作以避免数据损坏。有关更多信息,请参阅threadsafety
。factory (Connection) –
Connection
的自定义子类,用于创建连接,而不是默认的Connection
类。cached_statements (整数) –
sqlite3
应为此连接内部缓存的语句数,以避免解析开销。默认情况下为 128 条语句。uri (布尔值) – 如果设置为
True
,则 *database* 将被解释为包含文件路径和可选查询字符串的 URI。方案部分 *必须* 是"file:"
,并且路径可以是相对的或绝对的。查询字符串允许将参数传递给 SQLite,从而启用各种 如何使用 SQLite URI。autocommit (布尔值) – 控制 PEP 249 事务处理行为。有关更多信息,请参阅
Connection.autocommit
和 通过 autocommit 属性进行事务控制。autocommit 当前默认为LEGACY_TRANSACTION_CONTROL
。在未来的 Python 版本中,默认值将更改为False
。
- 返回类型:
引发一个 审计事件
sqlite3.connect
,参数为database
。引发一个 审计事件
sqlite3.connect/handle
,参数为connection_handle
。3.4 版本中已更改: 添加了 uri 参数。
3.7 版本中已更改: database 现在也可以是 类路径对象,而不仅仅是字符串。
3.10 版本中已更改: 添加了
sqlite3.connect/handle
审计事件。3.12 版本中已更改: 添加了 autocommit 参数。
3.13 版本中已更改: 参数 timeout, detect_types, isolation_level, check_same_thread, factory, cached_statements 和 uri 的位置参数用法已弃用。它们将在 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, /)¶
启用或禁用回调回溯。默认情况下,您不会在用户定义函数、聚合、转换器、授权器回调等中获得任何回溯。如果您想调试它们,可以调用此函数并将 *flag* 设置为
True
。之后,您将在sys.stderr
上获取回调的回溯。使用False
再次禁用该功能。备注
用户定义函数回调中的错误将作为不可引发的异常记录。使用
unraisable hook handler
来检查失败的回调。
- sqlite3.register_adapter(type, adapter, /)¶
注册一个 *adapter* 可调用对象,用于将 Python 类型 *type* 适配为 SQLite 类型。适配器以 *type* 类型的 Python 对象作为其唯一参数调用,并且必须返回 SQLite 原生理解的类型 的值。
模块常量¶
- sqlite3.LEGACY_TRANSACTION_CONTROL¶
将
autocommit
设置为此常量以选择旧式(Python 3.12 之前)事务控制行为。有关更多信息,请参阅 通过 isolation_level 属性进行事务控制。
- 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
使用|
(按位或)运算符结合使用。备注
生成字段(例如
MAX(p)
)作为str
返回。使用PARSE_COLNAMES
为此类查询强制执行类型。
- sqlite3.PARSE_COLNAMES¶
将此标志值传递给
connect()
的 *detect_types* 参数,以使用从查询列名解析出的类型名作为转换器字典键来查找转换函数。查询列名必须用双引号 ("
) 包裹,类型名必须用方括号 ([]
) 包裹。SELECT MAX(p) as "p [point]" FROM test; ! will look up converter "point"
此标志可以与
PARSE_DECLTYPES
使用|
(按位或)运算符结合使用。
- 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.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 文档:数据库连接配置选项
自 3.12 版本弃用,在 3.14 版本中删除: version
和 version_info
常量。
连接对象¶
- class sqlite3.Connection¶
每个打开的 SQLite 数据库都由一个
Connection
对象表示,该对象使用sqlite3.connect()
创建。它们的主要目的是创建Cursor
对象和 事务控制。3.13 版本中已更改: 如果在
Connection
对象被删除之前未调用close()
,则会发出ResourceWarning
。SQLite 数据库连接具有以下属性和方法
- cursor(factory=Cursor)¶
创建并返回一个
Cursor
对象。游标方法接受一个可选参数 *factory*。如果提供,它必须是一个 可调用对象,返回Cursor
或其子类的实例。
- blobopen(table, column, rowid, /, *, 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 函数。
- 参数:
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 版本中已更改: 将 *name*、*narg* 和 *func* 作为关键字参数传递已弃用。这些参数将在 Python 3.15 中成为仅位置参数。
- create_aggregate(name, n_arg, aggregate_class)¶
创建或删除用户定义的 SQL 聚合函数。
- 参数:
name (字符串) – SQL 聚合函数的名称。
n_arg (整数) – 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()
3.13 版本中已更改: 将 *name*、*n_arg* 和 *aggregate_class* 作为关键字参数传递已弃用。这些参数将在 Python 3.15 中成为仅位置参数。
- create_window_function(name, num_params, aggregate_class, /)¶
创建或删除用户定义的聚合窗口函数。
- 参数:
name (字符串) – 要创建或删除的 SQL 聚合窗口函数的名称。
num_params (整数) – 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
禁用授权器的支持。3.13 版本中已更改: 将 *authorizer_callback* 作为关键字参数传递已弃用。该参数将在 Python 3.15 中成为仅位置参数。
- set_progress_handler(progress_handler, n)¶
注册 可调用对象 *progress_handler*,以便每 *n* 条 SQLite 虚拟机指令都会调用它。这对于在长时间运行的操作期间从 SQLite 接收调用很有用,例如更新 GUI。
如果您想清除任何以前安装的进度处理程序,请将 *progress_handler* 设置为
None
调用此方法。从处理程序函数返回非零值将终止当前正在执行的查询,并导致它引发
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, /)¶
如果 *enabled* 为
True
,则允许 SQLite 引擎从共享库加载 SQLite 扩展;否则,禁止加载 SQLite 扩展。SQLite 扩展可以定义新函数、聚合或全新的虚拟表实现。一个著名的扩展是随 SQLite 分发的全文搜索扩展。备注
sqlite3
模块默认不构建为支持可加载扩展,因为某些平台(特别是 macOS)的 SQLite 库在编译时未包含此功能。要获得可加载扩展支持,您必须将--enable-loadable-sqlite-extensions
选项传递给 configure。引发一个 审计事件
sqlite3.enable_load_extension
,参数为connection
、enabled
。在 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()
启用扩展加载。- 参数:
引发一个 审计事件
sqlite3.load_extension
,参数为connection
、path
。在 3.2 版本加入。
3.10 版本中已更改: 添加了
sqlite3.load_extension
审计事件。3.12 版本中已更改: 添加了 *entrypoint* 参数。
- iterdump(*, filter=None)¶
返回一个 迭代器,用于将数据库转储为 SQL 源代码。在保存内存数据库以便以后恢复时很有用。类似于 sqlite3 shell 中的
.dump
命令。- 参数:
filter (字符串 | 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 (整数) – 每次复制的页数。如果等于或小于
0
,则整个数据库将一次性复制。默认为-1
。progress (回调函数 | None) – 如果设置为 可调用对象,则在每次备份迭代时调用它,并带三个整数参数:上次迭代的 *status*、仍要复制的 *remaining* 页数和 *total* 页数。默认为
None
。name (字符串) – 要备份的数据库名称。可以是
"main"
(默认)表示主数据库,"temp"
表示临时数据库,或使用ATTACH DATABASE
SQL 语句附加的自定义数据库名称。sleep (浮点数) – 在连续尝试备份剩余页面之间休眠的秒数。
示例 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 (整数) – 要查询的 SQLite 限制类别。
- 返回类型:
- 引发:
ProgrammingError – 如果底层 SQLite 库无法识别 *category*。
例如,查询
Connection
con
的 SQL 语句最大长度(默认为 1000000000)>>> con.getlimit(sqlite3.SQLITE_LIMIT_SQL_LENGTH) 1000000000
在 3.11 版本中新增。
- setlimit(category, limit, /)¶
设置连接运行时限制。尝试将限制增加到其硬上限以上时,将静默截断为硬上限。无论限制是否更改,都返回限制的先前值。
- 参数:
category (整数) – 要设置的 SQLite 限制类别。
limit (整数) – 新限制的值。如果为负数,则当前限制不变。
- 返回类型:
- 引发:
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 (整数) – 一个 SQLITE_DBCONFIG 代码。
- 返回类型:
3.12 新版功能.
- setconfig(op, enable=True, /)¶
设置布尔连接配置选项。
- 参数:
op (整数) – 一个 SQLITE_DBCONFIG 代码。
enable (布尔值) – 如果应启用配置选项,则为
True
(默认);如果应禁用,则为False
。
3.12 新版功能.
- serialize(*, name='main')¶
将数据库序列化为
bytes
对象。对于普通的磁盘数据库文件,序列化只是磁盘文件的副本。对于内存数据库或“临时”数据库,序列化是如果该数据库被备份到磁盘时将写入磁盘的相同字节序列。备注
此方法仅在底层 SQLite 库具有 serialize API 时可用。
在 3.11 版本中新增。
- deserialize(data, /, *, name='main')¶
将
serialized
数据库反序列化到Connection
中。此方法会使数据库连接从数据库 name 断开,然后根据 data 中包含的序列化将 name 作为内存数据库重新打开。- 参数:
- 引发:
OperationalError – 如果数据库连接当前正在参与读取事务或备份操作。
DatabaseError – 如果 data 不包含有效的 SQLite 数据库。
OverflowError – 如果
len(data)
大于2**63 - 1
。
备注
此方法仅在底层 SQLite 库具有 deserialize 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
。isolation_level
只有在autocommit
设置为LEGACY_TRANSACTION_CONTROL
(默认值)时才有效。
- 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
| sequence) – 要绑定到 sql 中占位符的 Python 值。如果使用命名占位符,则为dict
。如果使用未命名占位符,则为 序列。请参阅 如何在 SQL 查询中使用占位符绑定值。
- 引发:
ProgrammingError – 当 sql 包含多个 SQL 语句时。当使用 命名占位符 且 parameters 是序列而不是
dict
时。
如果
autocommit
是LEGACY_TRANSACTION_CONTROL
,isolation_level
不是None
,sql 是INSERT
、UPDATE
、DELETE
或REPLACE
语句,并且没有打开的事务,则在执行 sql 之前会隐式打开一个事务。3.14 版本中已更改: 如果使用 命名占位符 并且 parameters 是序列而不是
dict
,则会发出ProgrammingError
。使用
executescript()
执行多个 SQL 语句。
- executemany(sql, parameters, /)¶
对于 parameters 中的每个项目,重复执行 参数化 DML SQL 语句 sql。
使用与
execute()
相同的隐式事务处理。- 参数:
sql (str) – 单个 SQL DML 语句。
parameters (iterable) – 用于绑定 sql 中占位符的参数的 可迭代对象。请参阅 如何在 SQL 查询中使用占位符绑定值。
- 引发:
ProgrammingError – 当 sql 包含多个 SQL 语句或不是 DML 语句时。当使用 命名占位符 并且 parameters 中的项目是序列而不是
dict
时。
示例
rows = [ ("row1",), ("row2",), ] # cur is an sqlite3.Cursor object cur.executemany("INSERT INTO data VALUES(?)", rows)
备注
任何结果行都将被丢弃,包括带有 RETURNING 子句 的 DML 语句。
3.14 版本中已更改: 如果使用 命名占位符 并且 parameters 中的项目是序列而不是
dict
,则会发出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()
调用中保持相同的值。3.14.0(未发布)版本中已更改: 负 size 值将被拒绝,并引发
ValueError
。
- close()¶
立即关闭游标(而不是在调用
__del__
时)。从此时起,游标将无法使用;如果尝试对游标执行任何操作,将引发
ProgrammingError
异常。
- setinputsizes(sizes, /)¶
DB-API 所必需。在
sqlite3
中不执行任何操作。
- setoutputsize(size, column=None, /)¶
DB-API 所必需。在
sqlite3
中不执行任何操作。
- arraysize¶
读/写属性,控制
fetchmany()
返回的行数。默认值为 1,这意味着每次调用将获取单行。3.14.0(未发布)版本中已更改: 负值将被拒绝,并引发
ValueError
。
- connection¶
只读属性,提供属于游标的 SQLite 数据库
Connection
。通过调用con.cursor()
创建的Cursor
对象将具有一个引用 con 的connection
属性>>> 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()¶
返回一个
list
,其中包含作为strings
的列名。在查询之后,它是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
的子类。
- exception sqlite3.Error¶
此模块中其他异常的基类。使用此异常可在单个
except
语句中捕获所有错误。Error
是Exception
的子类。如果异常源于 SQLite 库内部,则以下两个属性将添加到异常中
- sqlite_errorcode¶
来自 SQLite API 的数字错误代码
在 3.11 版本中新增。
- sqlite_errorname¶
来自 SQLite API 的数字错误代码的符号名称
在 3.11 版本中新增。
- exception sqlite3.InterfaceError¶
由于误用低级 SQLite C API 而引发的异常。换句话说,如果引发此异常,则可能表示
sqlite3
模块中存在错误。InterfaceError
是Error
的子类。
- exception sqlite3.DatabaseError¶
由于与数据库相关的错误而引发的异常。这作为几种数据库错误的基异常。它仅通过专门的子类隐式引发。
DatabaseError
是Error
的子类。
- exception sqlite3.DataError¶
由于处理数据的问题(例如数值超出范围,字符串过长)而引发的异常。
DataError
是DatabaseError
的子类。
- exception sqlite3.OperationalError¶
由于与数据库操作相关的错误而引发的异常,不一定在程序员的控制之下。例如,找不到数据库路径,或者事务无法处理。
OperationalError
是DatabaseError
的子类。
- exception sqlite3.IntegrityError¶
当数据库的参照完整性受到影响时(例如外键检查失败)引发的异常。它是
DatabaseError
的子类。
- exception sqlite3.InternalError¶
当 SQLite 遇到内部错误时引发的异常。如果引发此异常,可能表示运行时 SQLite 库存在问题。
InternalError
是DatabaseError
的子类。
- exception sqlite3.ProgrammingError¶
由于
sqlite3
API 编程错误而引发的异常,例如向查询提供错误的绑定数量,或尝试对已关闭的Connection
进行操作。ProgrammingError
是DatabaseError
的子类。
- exception 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
模块的类型系统可以通过两种方式扩展:您可以通过 对象适配器 在 SQLite 数据库中存储额外的 Python 类型,并且您可以通过 转换器 让 sqlite3
模块将 SQLite 类型转换为 Python 类型。
默认适配器和转换器(已弃用)¶
备注
默认适配器和转换器自 Python 3.12 起已弃用。请改用 适配器和转换器示例 并根据您的需求进行调整。
已弃用的默认适配器和转换器包括
一个将
datetime.date
对象适配为 ISO 8601 格式的字符串
的适配器。一个将
datetime.datetime
对象适配为 ISO 8601 格式字符串的适配器。一个将 声明的 “date” 类型转换为
datetime.date
对象的转换器。一个将声明的“timestamp”类型转换为
datetime.datetime
对象的转换器。小数部分将被截断为 6 位(微秒精度)。
备注
默认的“timestamp”转换器会忽略数据库中的 UTC 偏移量,并始终返回一个 naive 的 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 的参数替换。要将变量插入查询字符串,请在字符串中使用占位符,并通过将实际值作为 tuple
传递给游标的 execute()
方法的第二个参数,将其替换到查询中。
SQL 语句可以使用两种占位符之一:问号(qmark 风格)或命名占位符(命名风格)。对于 qmark 风格,parameters 必须是一个 序列,其长度必须与占位符的数量匹配,否则会引发 ProgrammingError
。对于命名风格,parameters 必须是 dict
(或其子类)的实例,其中必须包含所有命名参数的键;任何多余的项目都将被忽略。以下是两种风格的示例
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 原生仅支持有限的数据类型集。要将自定义 Python 类型存储在 SQLite 数据库中,请将它们 适配 为 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
对象。
备注
转换器函数 总是 传递一个 bytes
对象,无论底层 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.replace(tzinfo=None).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)
如何使用连接快捷方法¶
通过使用 Connection
类的 execute()
、executemany()
和 executescript()
方法,您的代码可以写得更简洁,因为您不必显式创建(通常是多余的)Cursor
对象。相反,Cursor
对象会被隐式创建,并且这些快捷方法会返回游标对象。这样,您只需在 Connection
对象上进行一次调用,即可执行 SELECT
语句并直接遍历它。
# 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
>>> 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
作为属性存在于 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
来适配数据类型为 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 不支持包含代理字符的字符串。
参见
说明¶
事务控制¶
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 自动提交模式。
无论 isolation_level
的值如何,executescript()
方法在执行给定的 SQL 脚本之前都会隐式提交任何挂起事务。
3.6 版本变更: sqlite3
过去会在 DDL 语句之前隐式提交一个未完成的事务。现在不再是这样了。
3.12 版本变更: 现在推荐通过 autocommit
属性来控制事务。