sqlite3
---用于sqlite数据库的db-api 2.0接口¶
源代码: Lib/sqlite3/
sqlite是一个C库,它提供了一个基于磁盘的轻量级数据库,不需要单独的服务器进程,并且允许使用非标准的SQL查询语言变体访问数据库。一些应用程序可以使用sqlite进行内部数据存储。也可以使用sqlite对应用程序进行原型化,然后将代码移植到更大的数据库,如postgresql或oracle。
sqlite3模块是由Gerhard Häring编写的。它提供了一个SQL接口,符合由描述的DB-API 2.0规范 PEP 249 ,并且需要SQLite 3.7.15或更高版本。
要使用该模块,必须首先创建一个 Connection
表示数据库的对象。数据将存储在 example.db
文件::
import sqlite3
conn = sqlite3.connect('example.db')
您还可以提供特殊名称 :memory:
在RAM中创建数据库。
一旦你拥有了 Connection
,您可以创建一个 Cursor
对象并调用其 execute()
执行SQL命令的方法:
c = conn.cursor()
# Create table
c.execute('''CREATE TABLE stocks
(date text, trans text, symbol text, qty real, price real)''')
# Insert a row of data
c.execute("INSERT INTO stocks VALUES ('2006-01-05','BUY','RHAT',100,35.14)")
# Save (commit) the changes
conn.commit()
# We can also close the connection if we are done with it.
# Just be sure any changes have been committed or they will be lost.
conn.close()
您保存的数据是永久性的,可以在后续会话中使用:
import sqlite3
conn = sqlite3.connect('example.db')
c = conn.cursor()
通常,您的SQL操作需要使用来自python变量的值。您不应该使用python的字符串操作来组装查询,因为这样做是不安全的;它使您的程序容易受到SQL注入攻击(请参阅https://xkcd.com/327/了解可能出错的幽默示例)。
相反,使用db-api的参数替换。放 ?
作为占位符使用值,然后提供值的元组作为光标的第二个参数 execute()
方法。(其他数据库模块可能使用不同的占位符,例如 %s
或 :1
)例如:
# Never do this -- insecure!
symbol = 'RHAT'
c.execute("SELECT * FROM stocks WHERE symbol = '%s'" % symbol)
# Do this instead
t = ('RHAT',)
c.execute('SELECT * FROM stocks WHERE symbol=?', t)
print(c.fetchone())
# Larger example that inserts many records at a time
purchases = [('2006-03-28', 'BUY', 'IBM', 1000, 45.00),
('2006-04-05', 'BUY', 'MSFT', 1000, 72.00),
('2006-04-06', 'SELL', 'IBM', 500, 53.00),
]
c.executemany('INSERT INTO stocks VALUES (?,?,?,?,?)', purchases)
要在执行select语句后检索数据,可以将光标视为 iterator ,调用光标的 fetchone()
方法来检索单个匹配行或调用 fetchall()
获取匹配行的列表。
此示例使用迭代器形式:
>>> for row in c.execute('SELECT * FROM stocks ORDER BY price'):
print(row)
('2006-01-05', 'BUY', 'RHAT', 100, 35.14)
('2006-03-28', 'BUY', 'IBM', 1000, 45.0)
('2006-04-06', 'SELL', 'IBM', 500, 53.0)
('2006-04-05', 'BUY', 'MSFT', 1000, 72.0)
参见
- https://github.com/ghaering/pysqlite
pysqlite网页——sqlite3是在外部以“pysqlite”的名称开发的。
- https://www.sqlite.org
sqlite网页;文档描述支持的SQL方言的语法和可用数据类型。
- https://www.w3schools.com/sql/
学习SQL语法的教程、参考和示例。
- PEP 249 -数据库API规范2.0
马克·安德尔·莱姆伯格写的PEP。
模块函数和常量¶
- sqlite3.version¶
作为字符串的此模块的版本号。这不是sqlite库的版本。
- sqlite3.version_info¶
此模块的版本号,作为整数的元组。这不是sqlite库的版本。
- sqlite3.sqlite_version¶
作为字符串的运行时sqlite库的版本号。
- sqlite3.sqlite_version_info¶
作为整数元组的运行时sqlite库的版本号。
- sqlite3.PARSE_DECLTYPES¶
此常量用于 detect_types 的参数
connect()
功能。设置它会使
sqlite3
模块为它返回的每个列分析声明的类型。它将解析出声明类型的第一个字,即对于“整数主键”,它将解析出“整数”,对于“数字(10)”,它将解析出“数字”。然后,对于该列,它将查看转换器字典,并使用为该类型注册的转换器函数。
- sqlite3.PARSE_COLNAMES¶
此常量用于 detect_types 的参数
connect()
功能。设置此选项将使sqlite接口解析它返回的每一列的列名。它将查找形成的字符串 [MyType] 然后确定“mytype”是列的类型。它将尝试在转换器字典中找到“mytype”的条目,然后使用在那里找到的转换器函数返回值。在中找到的列名称
Cursor.description
不包括类型,即如果您使用'as "Expiration date [datetime]"'
在您的SQL中,我们将解析所有内容,直到第一个'['
对于列名并去掉前面的空格:列名只是“过期日期”。
- sqlite3.connect(database[, timeout, detect_types, isolation_level, check_same_thread, factory, cached_statements, uri])¶
打开与sqlite数据库文件的连接 database . 默认情况下返回
Connection
对象,除非自定义 工厂 给出。database 是一个 path-like object 提供要打开的数据库文件的路径名(绝对或相对于当前工作目录)。你可以用
":memory:"
打开与RAM中而不是磁盘上的数据库的数据库连接。当一个数据库被多个连接访问,并且其中一个进程修改该数据库时,SQLite数据库将被锁定,直到提交该事务为止。这个 timeout 参数指定连接在引发异常之前应等待锁消失的时间。超时参数的默认值为5.0(5秒)。
对于 isolation_level 参数,请参见
isolation_level
性质Connection
物体。sqlite本机只支持类型text、integer、real、blob和null。如果要使用其他类型,必须自己添加对它们的支持。这个 detect_types 参数和使用自定义 converters 在模块级注册
register_converter()
函数允许您轻松地执行该操作。detect_types 默认值为0(即关闭,不检测类型),您可以将其设置为
PARSE_DECLTYPES
和PARSE_COLNAMES
若要打开类型检测,请执行以下操作。由于SQLite行为,无法检测生成的字段的类型(例如max(data)
),即使当 detect_types 参数已设置。在这种情况下,返回的类型为str
。默认情况下, check_same_thread 是
True
只有创建线程可以使用连接。如果设置False
,返回的连接可以跨多个线程共享。当使用具有相同连接的多个线程时,用户应序列化写入操作,以避免数据损坏。默认情况下,
sqlite3
模块使用它的Connection
Connect调用的类。但是,您可以将Connection
等级和品牌connect()
使用您的类,而不是提供您的类 工厂 参数。查阅本节 sqlite和python类型 有关详细信息,请参阅本手册。
这个
sqlite3
模块内部使用语句缓存来避免SQL解析开销。如果要显式设置为连接缓存的语句数,可以设置 cached_statements 参数。当前实现的默认值是缓存100条语句。如果 uri 是真的, database 被解释为URI。这允许您指定选项。例如,要以只读模式打开数据库,可以使用:
db = sqlite3.connect('file:path/to/database?mode=ro', uri=True)
有关此功能的详细信息,包括可识别选项的列表,请参见 SQLite URI documentation .
提出一个 auditing event
sqlite3.connect
带着论证database
.在 3.4 版更改: 增加了 uri 参数。
在 3.7 版更改: database 现在也可以是 path-like object 不只是一个字符串。
- sqlite3.register_converter(typename, callable)¶
注册一个可调用函数,以便将字节串从数据库转换为自定义的python类型。将为类型为的所有数据库值调用Callable。 类别名 . 授予参数 detect_types 的
connect()
用于类型检测工作方式的函数。注意 类别名 查询中类型的名称以不区分大小写的方式匹配。
- sqlite3.register_adapter(type, callable)¶
注册可调用的以转换自定义python类型 type 到sqlite支持的类型之一。可赎回的 可赎回的 接受python值作为单个参数,并且必须返回以下类型的值:int、float、str或bytes。
- sqlite3.complete_statement(sql)¶
返回
True
如果字符串 sql 包含一个或多个以分号结尾的完整SQL语句。它不验证SQL是否语法正确,只验证没有未闭合的字符串文本,并且语句以分号结尾。这可用于为sqlite构建shell,如下例所示:
# A minimal SQLite shell for experiments import sqlite3 con = sqlite3.connect(":memory:") con.isolation_level = None cur = con.cursor() buffer = "" print("Enter your SQL commands to execute in sqlite3.") print("Enter a blank line to exit.") while True: line = input() if line == "": break buffer += line if sqlite3.complete_statement(buffer): try: buffer = buffer.strip() cur.execute(buffer) if buffer.lstrip().upper().startswith("SELECT"): print(cur.fetchall()) except sqlite3.Error as e: print("An error occurred:", e.args[0]) buffer = "" con.close()
连接对象¶
- class sqlite3.Connection¶
SQLite数据库连接具有以下属性和方法:
- commit()¶
此方法提交当前事务。如果不调用此方法,则自上次调用以来所做的任何操作
commit()
在其他数据库连接中不可见。如果您想知道为什么看不到已写入数据库的数据,请检查您是否忘记调用此方法。
- executemany(sql[, parameters])¶
这是一个非标准的快捷方式,通过调用
cursor()
方法,调用光标的executemany()
方法与 参数 并返回光标。
- executescript(sql_script)¶
这是一个非标准的快捷方式,通过调用
cursor()
方法,调用光标的executescript()
给定的方法 sql_script ,并返回光标。
- create_function(name, num_params, func, *, deterministic=False)¶
创建一个用户定义函数,以后可以在函数名下的SQL语句中使用该函数 name . num_params 是函数接受的参数数目(如果 num_params 是-1,函数可以接受任意数量的参数),并且 func 是作为SQL函数调用的python可调用函数。如果 确定性的 为true,创建的函数标记为 deterministic ,从而允许sqlite执行其他优化。sqlite 3.8.3或更高版本支持此标志,
NotSupportedError
如果与旧版本一起使用,将引发。函数可以返回sqlite支持的任何类型:bytes、str、int、float和
None
.在 3.8 版更改: 这个 确定性的 已添加参数。
例子:
import sqlite3 import hashlib def md5sum(t): return hashlib.md5(t).hexdigest() con = sqlite3.connect(":memory:") con.create_function("md5", 1, md5sum) cur = con.cursor() cur.execute("select md5(?)", (b"foo",)) print(cur.fetchone()[0]) con.close()
- create_aggregate(name, num_params, aggregate_class)¶
创建用户定义的聚合函数。
聚合类必须实现
step
方法,它接受参数个数 num_params (如果 num_params 是-1,函数可以接受任意数量的参数),并且finalize
将返回聚合的最终结果的方法。这个
finalize
方法可以返回sqlite支持的任何类型:bytes、str、int、float和None
.例子:
import sqlite3 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.cursor() cur.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_collation(name, callable)¶
使用指定的 name 和 可赎回的 . 可调用的将传递两个字符串参数。如果第一个排序低于第二个,则返回-1;如果第一个排序等于第二个,则返回0;如果第一个排序高于第二个,则返回1。注意,这控制排序(在SQL中按顺序排序),这样比较就不会影响其他SQL操作。
请注意,可调用文件将以python字节串的形式获取其参数,通常以utf-8编码。
下面的示例显示了一个自定义排序规则,它对“错误的方式”进行排序:
import sqlite3 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.cursor() cur.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()
要删除排序规则,请调用
create_collation
具有None
可调用:con.create_collation("reverse", None)
- interrupt()¶
您可以从其他线程调用此方法以中止可能在连接上执行的任何查询。然后查询将中止,调用方将获得异常。
- set_authorizer(authorizer_callback)¶
此例程注册回调。每次尝试访问数据库中表的列时都会调用回调。回调应该返回
SQLITE_OK
如果允许访问,SQLITE_DENY
如果整个SQL语句因错误而中止,并且SQLITE_IGNORE
如果该列应被视为空值。这些常量在sqlite3
模块。回调的第一个参数表示要授权哪种操作。第二个和第三个参数将是参数或
None
取决于第一个参数。第4个参数是数据库的名称(“main”、“temp”等),如果适用。第5个参数是负责访问尝试或None
如果此访问尝试直接来自输入SQL代码。请参考sqlite文档,了解第一个参数的可能值以及第二个和第三个参数的含义(取决于第一个参数)。所有必需的常量都可以在
sqlite3
模块。
- set_progress_handler(handler, n)¶
此例程注册回调。对每个 n sqlite虚拟机的指令。如果您希望在长时间运行操作(例如更新GUI)期间从sqlite调用,那么这非常有用。
如果要清除以前安装的任何进度处理程序,请使用
None
对于 处理程序 .从handler函数返回非零值将终止当前正在执行的查询,并导致它引发
OperationalError
例外。
- set_trace_callback(trace_callback)¶
寄存器 trace_callback 为每个实际由SQLite后端执行的SQL语句调用。
传递给回调的唯一参数是正在执行的语句(字符串)。回调的返回值被忽略。注意,后端不仅运行传递给
Cursor.execute()
方法。其他来源包括python模块的事务管理和当前数据库中定义的触发器的执行。经过
None
作为 trace_callback 将禁用跟踪回调。3.3 新版功能.
- enable_load_extension(enabled)¶
此例程允许/禁止sqlite引擎从共享库加载sqlite扩展。SQLite扩展可以定义新的函数、聚合或整个新的虚拟表实现。一个众所周知的扩展是与sqlite一起分发的全文搜索扩展。
默认情况下禁用可加载扩展。见 1.
3.2 新版功能.
import sqlite3 con = sqlite3.connect(":memory:") # enable extension loading 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) con.close()
- load_extension(path)¶
此例程从共享库加载一个sqlite扩展。您必须启用扩展加载
enable_load_extension()
在你能使用这个程序之前。默认情况下禁用可加载扩展。见 1.
3.2 新版功能.
- row_factory¶
您可以将此属性更改为可调用的,它接受光标和原始行作为元组,并返回实际的结果行。通过这种方式,您可以实现更高级的返回结果的方法,例如返回一个还可以按名称访问列的对象。
例子:
import sqlite3 def dict_factory(cursor, row): d = {} for idx, col in enumerate(cursor.description): d[col[0]] = row[idx] return d con = sqlite3.connect(":memory:") con.row_factory = dict_factory cur = con.cursor() cur.execute("select 1 as a") print(cur.fetchone()["a"]) con.close()
如果返回元组还不够,并且您希望基于名称访问列,那么应该考虑设置
row_factory
到高度优化的sqlite3.Row
类型。Row
提供对列的基于索引和不区分大小写的基于名称的访问,几乎没有内存开销。它可能会比您自己的基于字典的自定义方法更好,甚至比基于数据库行的解决方案更好。
- text_factory¶
使用此属性,可以控制返回的对象
TEXT
数据类型。默认情况下,此属性设置为str
以及sqlite3
模块将返回的Unicode对象TEXT
. 如果要返回bytestrings,可以将其设置为bytes
.您还可以将其设置为接受单个字节字符串参数并返回结果对象的任何其他可调用对象。
请参见以下示例代码以获取说明:
import sqlite3 con = sqlite3.connect(":memory:") cur = con.cursor() AUSTRIA = "\xd6sterreich" # by default, rows are returned as Unicode cur.execute("select ?", (AUSTRIA,)) row = cur.fetchone() assert row[0] == AUSTRIA # but we can make sqlite3 always return bytestrings ... con.text_factory = bytes cur.execute("select ?", (AUSTRIA,)) row = cur.fetchone() assert type(row[0]) is bytes # the bytestrings will be encoded in UTF-8, unless you stored garbage in the # database ... assert row[0] == AUSTRIA.encode("utf-8") # we can also implement a custom text_factory ... # here we implement one that appends "foo" to all strings con.text_factory = lambda x: x.decode("utf-8") + "foo" cur.execute("select ?", ("bar",)) row = cur.fetchone() assert row[0] == "barfoo" con.close()
- total_changes¶
返回自数据库连接打开以来已修改、插入或删除的数据库行的总数。
- iterdump()¶
返回迭代器以SQL文本格式转储数据库。在保存内存中的数据库以便以后恢复时很有用。此功能提供与 .dump 命令在 sqlite3 壳牌。
例子::
# Convert file existing_db.db to SQL dump file dump.sql import sqlite3 con = sqlite3.connect('existing_db.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.25)¶
这个方法可以备份一个sqlite数据库,即使它正在被其他客户机访问,或者同时被同一个连接访问。副本将写入强制参数 目标 那一定是另一个
Connection
实例。默认情况下,或何时 页 要么是
0
或者负整数,整个数据库将在一个步骤中复制;否则,该方法将执行循环复制,最多复制到 页 一次一页。如果 进步 是指定的,它必须
None
或者一个可调用的对象,该对象将在每次迭代中使用三个整型参数分别执行 地位 上一次迭代的 剩下的 仍要复制的页数和 全部的 页数。这个 name 参数指定要复制的数据库名称:它必须是包含
"main"
,默认值,指示主数据库,"temp"
指示临时数据库或在AS
关键字在ATTACH DATABASE
附加数据库的语句。这个 睡觉 参数指定在连续尝试备份剩余页之间休眠的秒数,可以指定为整数或浮点值。
示例1:将现有数据库复制到另一个数据库:
import sqlite3 def progress(status, remaining, total): print(f'Copied {total-remaining} of {total} pages...') con = sqlite3.connect('existing_db.db') bck = sqlite3.connect('backup.db') with bck: con.backup(bck, pages=1, progress=progress) bck.close() con.close()
示例2,将现有数据库复制到临时副本中:
import sqlite3 source = sqlite3.connect('existing_db.db') dest = sqlite3.connect(':memory:') source.backup(dest)
3.7 新版功能.
游标对象¶
- class sqlite3.Cursor¶
A
Cursor
实例具有以下属性和方法。- execute(sql[, parameters])¶
执行SQL语句。SQL语句可以参数化(即占位符而不是SQL文本)。这个
sqlite3
模块支持两种占位符:问号(qmark样式)和命名占位符(命名样式)。以下是两种样式的示例:
import sqlite3 con = sqlite3.connect(":memory:") cur = con.cursor() cur.execute("create table people (name_last, age)") who = "Yeltsin" age = 72 # This is the qmark style: cur.execute("insert into people values (?, ?)", (who, age)) # And this is the named style: cur.execute("select * from people where name_last=:who and age=:age", {"who": who, "age": age}) print(cur.fetchone()) con.close()
execute()
将只执行一条SQL语句。如果尝试用它执行多个语句,它将引发Warning
. 使用executescript()
如果要用一个调用执行多个SQL语句。
- executemany(sql, seq_of_parameters)¶
对序列中找到的所有参数序列或映射执行SQL命令 seq_of_parameters . 这个
sqlite3
模块还允许使用 iterator 生成参数而不是序列。import sqlite3 class IterChars: def __init__(self): self.count = ord('a') def __iter__(self): return self def __next__(self): if self.count > ord('z'): raise StopIteration self.count += 1 return (chr(self.count - 1),) # this is a 1-tuple con = sqlite3.connect(":memory:") cur = con.cursor() cur.execute("create table characters(c)") theIter = IterChars() cur.executemany("insert into characters(c) values (?)", theIter) cur.execute("select c from characters") print(cur.fetchall()) con.close()
下面是一个使用 generator :
import sqlite3 import string def char_generator(): for c in string.ascii_lowercase: yield (c,) con = sqlite3.connect(":memory:") cur = con.cursor() cur.execute("create table characters(c)") cur.executemany("insert into characters(c) values (?)", char_generator()) cur.execute("select c from characters") print(cur.fetchall()) con.close()
- executescript(sql_script)¶
这是一种同时执行多个SQL语句的非标准方便方法。它发布了一个
COMMIT
语句首先,然后执行作为参数获取的SQL脚本。sql_script 可以是的实例
str
.例子:
import sqlite3 con = sqlite3.connect(":memory:") cur = con.cursor() cur.executescript(""" create table person( firstname, lastname, age ); create table book( title, author, published ); insert into book(title, author, published) values ( 'Dirk Gently''s Holistic Detective Agency', 'Douglas Adams', 1987 ); """) con.close()
- fetchmany(size=cursor.arraysize)¶
获取查询结果的下一组行,返回列表。当没有更多行可用时,将返回空列表。
每个调用要获取的行数由 size 参数。如果未给定,则光标的arraysize将确定要提取的行数。该方法应尝试获取大小参数所指示的行数。如果由于指定的行数不可用而无法执行此操作,则返回的行数可能会更少。
注意:有性能方面的考虑 size 参数。为了获得最佳性能,通常最好使用arraysize属性。如果 size 使用参数,则最好保留一个
fetchmany()
调用下一个。
- fetchall()¶
获取查询结果的所有(剩余)行,返回列表。请注意,光标的arraysize属性可能会影响此操作的性能。如果没有可用的行,则返回空列表。
- close()¶
立即关闭光标(而不是在任何时候
__del__
被称为。从这一点向前光标将不可用;a
ProgrammingError
如果尝试对光标执行任何操作,将引发异常。
- rowcount¶
虽然
Cursor
类sqlite3
模块实现了这个属性,数据库引擎自己对确定“受影响的行数”/“选定的行数”的支持是很奇怪的。为了
executemany()
语句中,修改的次数汇总为rowcount
.根据python db api规范的要求,
rowcount
如果没有,则属性“为-1executeXX()
已在光标上执行,或者接口无法确定最后一个操作的行数”。这包括SELECT
语句,因为在提取所有行之前无法确定查询生成的行数。
- lastrowid¶
此只读属性提供最后修改行的rowID。只有在您发出
INSERT
或AREPLACE
语句使用execute()
方法。用于除INSERT
或REPLACE
或者什么时候executemany()
被称为lastrowid
设置为None
.如果
INSERT
或REPLACE
语句插入前一个成功的rowid失败。在 3.6 版更改: 增加了对
REPLACE
语句。
- arraysize¶
控制返回行数的读/写属性
fetchmany()
.默认值为1,这意味着每次调用都将提取一行。
- description¶
此只读属性提供上一个查询的列名。为了与python db api保持兼容,它为每列返回一个7元组,其中每个元组的最后6个项是
None
.它被设定为
SELECT
语句也没有任何匹配的行。
- connection¶
此只读属性提供了sqlite数据库
Connection
用于Cursor
对象。一Cursor
通过调用创建的对象con.cursor()
将有一个connection
引用的属性 con ::>>> con = sqlite3.connect(":memory:") >>> cur = con.cursor() >>> cur.connection == con True
行对象¶
- class sqlite3.Row¶
A
Row
实例作为高度优化的row_factory
对于Connection
物体。它试图模仿一个元组的大部分特性。它支持按列名和索引、迭代、表示、相等性测试和
len()
.如果两个
Row
对象具有完全相同的列,并且它们的成员相等,它们的比较相等。- keys()¶
此方法返回列名称列表。在查询之后,它是中每个元组的第一个成员
Cursor.description
.
在 3.5 版更改: 增加了对切片的支持。
假设我们按照上面给出的示例初始化一个表:
conn = sqlite3.connect(":memory:")
c = conn.cursor()
c.execute('''create table stocks
(date text, trans text, symbol text,
qty real, price real)''')
c.execute("""insert into stocks
values ('2006-01-05','BUY','RHAT',100,35.14)""")
conn.commit()
c.close()
现在我们插上插头 Row
在::
>>> conn.row_factory = sqlite3.Row
>>> c = conn.cursor()
>>> c.execute('select * from stocks')
<sqlite3.Cursor object at 0x7f4e7dd8fa80>
>>> r = c.fetchone()
>>> type(r)
<class 'sqlite3.Row'>
>>> tuple(r)
('2006-01-05', 'BUY', 'RHAT', 100.0, 35.14)
>>> len(r)
5
>>> r[2]
'RHAT'
>>> r.keys()
['date', 'trans', 'symbol', 'qty', 'price']
>>> r['qty']
100.0
>>> for member in r:
... print(member)
...
2006-01-05
BUY
RHAT
100.0
35.14
例外情况¶
- exception sqlite3.DatabaseError¶
为与数据库相关的错误引发异常。
- exception sqlite3.IntegrityError¶
当数据库的关系完整性受到影响时引发异常,例如外键检查失败。它是
DatabaseError
.
- exception sqlite3.ProgrammingError¶
由于编程错误引发的异常,例如:找不到表或表已存在、SQL语句中的语法错误、指定的参数数目错误等。它是
DatabaseError
.
- exception sqlite3.OperationalError¶
对与数据库操作相关且不一定受程序员控制的错误引发的异常,例如发生意外断开、找不到数据源名称、无法处理事务等。它是
DatabaseError
.
- exception sqlite3.NotSupportedError¶
如果使用了数据库不支持的方法或数据库API,例如调用
rollback()
方法对不支持事务或已关闭事务的连接。它是DatabaseError
.
sqlite和python类型¶
介绍¶
sqlite本机支持以下类型: NULL
, INTEGER
, REAL
, TEXT
, BLOB
.
因此,以下python类型可以毫无问题地发送到sqlite:
Python 型 |
SQLite型 |
---|---|
|
|
|
|
|
|
|
|
|
这是默认情况下将sqlite类型转换为python类型的方式:
SQLite型 |
Python 型 |
---|---|
|
|
|
|
|
|
|
取决于 |
|
的类型系统 sqlite3
模块有两种可扩展的方式:您可以通过对象适应将额外的python类型存储在一个sqlite数据库中,并且您可以让 sqlite3
模块通过转换器将sqlite类型转换为不同的python类型。
使用适配器在sqlite数据库中存储其他python类型¶
如前所述,SQLite只支持本机有限的一组类型。要将其他python类型与sqlite一起使用,必须 适应 它们是sqlite3模块支持的sqlite类型之一:nonetype、int、float、str、bytes。
有两种方法可以启用 sqlite3
模块以使自定义的python类型适应支持的类型之一。
让你的对象适应自己¶
如果你自己写这个类,这是一个很好的方法。假设你有这样一个类:
class Point:
def __init__(self, x, y):
self.x, self.y = x, y
现在要将点存储在单个SQLite列中。首先,必须选择一个支持的类型来表示点。让我们使用str并用分号分隔坐标。那么你需要给你的类一个方法 __conform__(self, protocol)
必须返回转换值。参数 协议 将 PrepareProtocol
.
import sqlite3
class Point:
def __init__(self, x, y):
self.x, self.y = x, y
def __conform__(self, protocol):
if protocol is sqlite3.PrepareProtocol:
return "%f;%f" % (self.x, self.y)
con = sqlite3.connect(":memory:")
cur = con.cursor()
p = Point(4.0, -3.2)
cur.execute("select ?", (p,))
print(cur.fetchone()[0])
con.close()
注册可调用的适配器¶
另一种可能性是创建一个将类型转换为字符串表示形式的函数,并用 register_adapter()
.
import sqlite3
class Point:
def __init__(self, x, y):
self.x, self.y = x, y
def adapt_point(point):
return "%f;%f" % (point.x, point.y)
sqlite3.register_adapter(Point, adapt_point)
con = sqlite3.connect(":memory:")
cur = con.cursor()
p = Point(4.0, -3.2)
cur.execute("select ?", (p,))
print(cur.fetchone()[0])
con.close()
这个 sqlite3
模块有两个用于Python内置的默认适配器 datetime.date
和 datetime.datetime
类型。现在让我们假设我们要储存 datetime.datetime
对象不在ISO表示中,而是作为UNIX时间戳。
import sqlite3
import datetime
import time
def adapt_datetime(ts):
return time.mktime(ts.timetuple())
sqlite3.register_adapter(datetime.datetime, adapt_datetime)
con = sqlite3.connect(":memory:")
cur = con.cursor()
now = datetime.datetime.now()
cur.execute("select ?", (now,))
print(cur.fetchone()[0])
con.close()
将sqlite值转换为自定义python类型¶
编写适配器可以将自定义的python类型发送到sqlite。但是为了使它真正有用,我们需要使python-to-sqlite-to-python往返工作。
输入转换器。
让我们回到 Point
类。我们将x和y坐标以分号分隔,作为字符串存储在sqlite中。
首先,我们将定义一个转换器函数,它接受字符串作为参数,并构造一个 Point
对象。
注解
转换器功能 总是 调用给 bytes
对象,无论您在哪个数据类型下将值发送到sqlite。
def convert_point(s):
x, y = map(float, s.split(b";"))
return Point(x, y)
现在你需要 sqlite3
模块知道您从数据库中选择的实际上是一个点。有两种方法可以做到这一点:
通过声明的类型隐式
通过列名显式地
这两种方法在第节中都有描述。 模块函数和常量 ,在常量的条目中 PARSE_DECLTYPES
和 PARSE_COLNAMES
.
下面的例子说明了这两种方法。
import sqlite3
class Point:
def __init__(self, x, y):
self.x, self.y = x, y
def __repr__(self):
return "(%f;%f)" % (self.x, self.y)
def adapt_point(point):
return ("%f;%f" % (point.x, point.y)).encode('ascii')
def convert_point(s):
x, y = list(map(float, s.split(b";")))
return Point(x, y)
# Register the adapter
sqlite3.register_adapter(Point, adapt_point)
# Register the converter
sqlite3.register_converter("point", convert_point)
p = Point(4.0, -3.2)
#########################
# 1) Using declared types
con = sqlite3.connect(":memory:", detect_types=sqlite3.PARSE_DECLTYPES)
cur = con.cursor()
cur.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()
#######################
# 1) Using column names
con = sqlite3.connect(":memory:", detect_types=sqlite3.PARSE_COLNAMES)
cur = con.cursor()
cur.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()
默认适配器和转换器¶
datetime模块中有日期和日期时间类型的默认适配器。它们将作为ISO日期/ISO时间戳发送到sqlite。
默认转换器以“日期”的名称注册 datetime.date
在“时间戳”的名称下 datetime.datetime
.
这样,在大多数情况下,您可以使用来自python的日期/时间戳而不需要任何额外的修改。适配器的格式也与实验性的sqlite日期/时间函数兼容。
下面的示例演示了这一点。
import sqlite3
import datetime
con = sqlite3.connect(":memory:", detect_types=sqlite3.PARSE_DECLTYPES|sqlite3.PARSE_COLNAMES)
cur = con.cursor()
cur.execute("create table test(d date, ts timestamp)")
today = datetime.date.today()
now = datetime.datetime.now()
cur.execute("insert into test(d, ts) values (?, ?)", (today, now))
cur.execute("select d, ts from test")
row = cur.fetchone()
print(today, "=>", row[0], type(row[0]))
print(now, "=>", row[1], type(row[1]))
cur.execute('select current_date as "d [date]", current_timestamp as "ts [timestamp]"')
row = cur.fetchone()
print("current_date", row[0], type(row[0]))
print("current_timestamp", row[1], type(row[1]))
con.close()
如果存储在sqlite中的时间戳的小数部分长于6个数字,则时间戳转换器将其值截断为微秒精度。
控制交易¶
底层 sqlite3
类库在 autocommit
默认模式,但python sqlite3
默认情况下,模块不会。
autocommit
模式意味着修改数据库的语句立即生效。一 BEGIN
或 SAVEPOINT
语句禁用 autocommit
模式和A COMMIT
,A ROLLBACK
,或者 RELEASE
最后一个事务结束后, autocommit
返回模式。
Python sqlite3
模块默认问题A BEGIN
statement implicitly before a Data Modification Language (DML) statement (i.e. INSERT
/UPDATE
/删除`/
replace```)。
你可以控制哪种 BEGIN
声明 sqlite3
通过 isolation_level 参数 connect()
调用,或通过 isolation_level
连接的属性。如果您指定否 isolation_level 平原 BEGIN
使用,相当于指定 DEFERRED
. 其他可能的值是 IMMEDIATE
和 EXCLUSIVE
.
您可以禁用 sqlite3
通过设置实现模块的隐式事务管理 isolation_level
到 None
. 这将留下基础 sqlite3
类库在 autocommit
模式。然后,您可以通过显式地发出 BEGIN
, ROLLBACK
, SAVEPOINT
和 RELEASE
代码中的语句。
在 3.6 版更改: sqlite3
用于在DDL语句之前隐式提交打开的事务。情况不再是这样了。
使用 sqlite3
有效地¶
使用快捷方式¶
使用非标准 execute()
, executemany()
和 executescript()
方法 Connection
对象,可以更简洁地编写代码,因为您不必创建(通常是多余的) Cursor
对象。相反, Cursor
对象是隐式创建的,这些快捷方式方法返回光标对象。这样,您可以执行 SELECT
语句并直接使用 Connection
对象。
import sqlite3
persons = [
("Hugo", "Boss"),
("Calvin", "Klein")
]
con = sqlite3.connect(":memory:")
# Create the table
con.execute("create table person(firstname, lastname)")
# Fill the table
con.executemany("insert into person(firstname, lastname) values (?, ?)", persons)
# Print the table contents
for row in con.execute("select firstname, lastname from person"):
print(row)
print("I just deleted", con.execute("delete from person").rowcount, "rows")
# close is not a shortcut method and it's not called automatically,
# so the connection object should be closed manually
con.close()
按名称而不是按索引访问列¶
一个有用的特性 sqlite3
模块是内置的 sqlite3.Row
类,设计为用作行工厂。
用此类封装的行可以通过索引(如元组)和不区分大小写的名称访问:
import sqlite3
con = sqlite3.connect(":memory:")
con.row_factory = sqlite3.Row
cur = con.cursor()
cur.execute("select 'John' as name, 42 as age")
for row in cur:
assert row[0] == row["name"]
assert row["name"] == row["nAmE"]
assert row[1] == row["age"]
assert row[1] == row["AgE"]
con.close()
将连接用作上下文管理器¶
连接对象可以用作自动提交或回滚事务的上下文管理器。如果发生异常,事务将回滚;否则,事务将提交:
import sqlite3
con = sqlite3.connect(":memory:")
con.execute("create table person (id integer primary key, firstname varchar unique)")
# Successful, con.commit() is called automatically afterwards
with con:
con.execute("insert into person(firstname) values (?)", ("Joe",))
# 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 person(firstname) values (?)", ("Joe",))
except sqlite3.IntegrityError:
print("couldn't add Joe twice")
# Connection object used as context manager only commits or rollbacks transactions,
# so the connection object should be closed manually
con.close()
脚注