python 标准库 sqlite3
今天是二十四节气的大寒
大寒,是二十四节气中的最后一个节气。斗指丑;太阳黄经为300°;公历1月20-21日交节。同小寒一样,大寒也是表示天气寒冷程度的节气。在我国部分地区,大寒不如小寒冷,但在某些年份和沿海少数地方,全年最低气温仍然会出现在大寒节气内。小寒、大寒是一年中雨水最少的时段。
兹大寒一过,新一年的节气就又轮回来了,正所谓冬去春来。大寒虽然寒冷,但因为已近春天,所以不会像大雪到冬至期间那样酷寒。这时节,人们开始忙着除旧饰新、腌制年肴、准备年货和各种祭祀供品、扫尘洁物,因为中国人最重要的节日——春节就要到了。
每日一词:
Cold
adj 冷,寒冷
例句:
It is the last one in January 20th of each year twenty-four solar term solar term, before and after the sun reaches 300 degrees for it”. It is cold weather, meaning extreme.
大寒是二十四节气中最后一个节气,每年1月20日前后太阳到达黄经300°时为”大寒”。大寒,是天气寒冷到极点的意思。
源码
源代码: Lib/sqlite3/
SQLite 是一个C语言库,它可以提供一种轻量级的基于磁盘的数据库,这种数据库不需要独立的服务器进程,也允许需要使用一种非标准的 SQL 查询语言来访问它。一些应用程序可以使用 SQLite 作为内部数据存储。可以用它来创建一个应用程序原型,然后再迁移到更大的数据库,比如 PostgreSQL 或 Oracle。
sqlite3 模块由 Gerhard Häring 编写。它提供了符合 DB-API 2.0 规范的接口,这个规范是 PEP 249。
要使用这个模块,必须先创建一个 Connection
对象,它代表数据库。下面例子中,数据将存储在 example.db
文件中:
1 | import sqlite3 |
你也可以使用 :memory:
来创建一个内存中的数据库
当有了 Connection
对象后,你可以创建一个 Cursor
游标对象,然后调用它的 execute()
方法来执行 SQL 语句:
1 | c = conn.cursor() |
这些数据被持久化保存了,而且可以在之后的会话中使用它们:
1 | import sqlite3 |
通常你的 SQL 操作需要使用一些 Python 变量的值。你不应该使用 Python 的字符串操作来创建你的查询语句,因为那样做不安全;它会使你的程序容易受到 SQL 注入攻击(在 https://xkcd.com/327/ 上有一个搞笑的例子,看看有什么后果)
推荐另外一种方法:使用 DB-API 的参数替换。在你的 SQL 语句中,使用 ?
占位符来代替值,然后把对应的值组成的元组做为 execute()
方法的第二个参数。(其他数据库可能会使用不同的占位符,比如 %s
或者 :1
)例如:
1 | # Never do this -- insecure! |
要在执行 SELECT 语句后获取数据,你可以把游标作为 iterator,然后调用它的 fetchone()
方法来获取一条匹配的行,也可以调用 fetchall()
来得到包含多个匹配行的列表。
下面是一个使用迭代器形式的例子:
1 | for row in c.execute('SELECT * FROM stocks ORDER BY price'): |
模块函数和常量
sqlite3.version
这个模块的版本号,是一个字符串。不是 SQLite 库的版本号。
sqlite3.version_info
这个模块的版本号,是一个由整数组成的元组。不是 SQLite 库的版本号。
sqlite3.sqlite_version
使用中的 SQLite 库的版本号,是一个字符串。
sqlite3.sqlite_version_info
使用中的 SQLite 库的版本号,是一个整数组成的元组。
sqlite3.PARSE_DECLTYPES
这个常量可以作为
connect()
函数的 detect_types 参数。设置这个参数后,
sqlite3
模块将解析它返回的每一列申明的类型。它会申明的类型的第一个单词,比如“integer primary key”,它会解析出“integer”,再比如“number(10)”,它会解析出“number”。然后,它会在转换器字典里查找那个类型注册的转换器函数,并调用它。sqlite3.PARSE_COLNAMES
sqlite3.connect
(database[, timeout, detect_types, isolation_level, check_same_thread, factory, cached_statements, uri])
连接 SQLite 数据库 database。默认返回 Connection
对象,除非使用了自定义的 factory 参数。
database 是准备打开的数据库文件的路径(绝对路径或相对于当前目录的相对路径),它是 path-like object。你也可以用 ":memory:"
在内存中打开一个数据库。
当一个数据库被多个连接访问的时候,如果其中一个进程修改这个数据库,在这个事务提交之前,这个 SQLite 数据库将会被一直锁定。timeout 参数指定了这个连接等待锁释放的超时时间,超时之后会引发一个异常。这个超时时间默认是 5.0(5秒)。
isolation_level 参数,请查看 Connection
对象的 isolation_level
属性。
SQLite 原生只支持5种类型:TEXT,INTEGER,REAL,BLOB 和 NULL。如果你想用其它类型,你必须自己添加相应的支持。使用 detect_types 参数和模块级别的 register_converter()
函数注册转换器 可以简单的实现。
detect_types 默认为0(即关闭,没有类型检测)。你也可以组合 PARSE_DECLTYPES
和 PARSE_COLNAMES
来开启类型检测。
默认情况下,check_same_thread 为 True
,只有当前的线程可以使用该连接。 如果设置为 False
,则多个线程可以共享返回的连接。 当多个线程使用同一个连接的时候,用户应该把写操作进行序列化,以避免数据损坏。
默认情况下,当调用 connect 方法的时候,sqlite3
模块使用了它的 Connection
类。当然,你也可以创建 Connection
类的子类,然后创建提供了 factory 参数的 connect()
方法。
详情请查阅当前手册的 SQLite 与 Python 类型 部分。
sqlite3
模块在内部使用语句缓存来避免 SQL 解析开销。 如果要显式设置当前连接可以缓存的语句数,可以设置 cached_statements 参数。 当前实现的默认值是缓存100条语句。
如果 uri 为真,则 database 被解释为 URI。 它允许您指定选项。 例如,以只读模式打开数据库:
1 | db = sqlite3.connect('file:path/to/database?mode=ro', uri=True) |
有关此功能的更多信息,包括已知选项的列表,可以在 SQLite URI 文档 <<https://www.sqlite.org/uri.html>>
_ 中找到。
sqlite3.register_converter
(typename, callable)注册一个回调对象 callable, 用来转换数据库中的字节串为自定的 Python 类型。所有类型为 typename 的数据库的值在转换时,都会调用这个回调对象。通过指定
connect()
函数的 detect-types 参数来设置类型检测的方式。注意,typename 与查询语句中的类型名进行匹配时不区分大小写。sqlite3.register_adapter
(type, callable)注册一个回调对象 callable,用来转换自定义Python类型为一个 SQLite 支持的类型。 这个回调对象 callable 仅接受一个 Python 值作为参数,而且必须返回以下某个类型的值:int,float,str 或 bytes。
sqlite3.complete_statement
(sql)如果字符串 sql 包含一个或多个完整的 SQL 语句(以分号结束)则返回
True
。它不会验证 SQL 语法是否正确,仅会验证字符串字面上是否完整,以及是否以分号结束。它可以用来构建一个 SQLite shell,下面是一个例子:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30# 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()sqlite3.enable_callback_tracebacks
(flag)默认情况下,您不会获得任何用户定义函数中的回溯消息,比如聚合,转换器,授权器回调等。如果要调试它们,可以设置 flag 参数为
True
并调用此函数。 之后,回调中的回溯信息将会输出到sys.stderr
。 再次使用False
来禁用该功能。连接对象(Connection)
class sqlite3.Connection
SQLite 数据库连接对象有如下的属性和方法:
isolation_level
获取或设置当前默认的隔离级别。 表示自动提交模式的
None
以及 “DEFERRED”, “IMMEDIATE” 或 “EXCLUSIVE” 其中之一。 详细描述请参阅 控制事务。in_transaction
cursor
(factory=Cursor)这个方法接受一个可选参数 factory,如果要指定这个参数,它必须是一个可调用对象,而且必须返回
Cursor
类的一个实例或者子类。commit
()这个方法提交当前事务。如果没有调用这个方法,那么从上一次提交
commit()
以来所有的变化在其他数据库连接上都是不可见的。如果你往数据库里写了数据,但是又查询不到,请检查是否忘记了调用这个方法。rollback
()这个方法回滚从上一次调用
commit()
以来所有数据库的改变。close
()关闭数据库连接。注意,它不会自动调用
commit()
方法。如果在关闭数据库连接之前没有调用commit()
,那么你的修改将会丢失!execute
(sql[, parameters])这是一个非标准的快捷方法,它会调用
cursor()
方法来创建一个游标对象,并使用给定的 parameters 参数来调用游标对象的execute()
方法,最后返回这个游标对象。executemany
(sql[, parameters])这是一个非标准的快捷方法,它会调用
cursor()
方法来创建一个游标对象,并使用给定的 parameters 参数来调用游标对象的executemany()
方法,最后返回这个游标对象。executescript
(sql_script)这是一个非标准的快捷方法,它会调用
cursor()
方法来创建一个游标对象,并使用给定的 sql_script 参数来调用游标对象的executescript()
方法,最后返回这个游标对象。create_function
(name, num_params, func, **, deterministic=False*)创建一个可以在 SQL 语句中使用的用户自定义函数,函数名为 name。 num_params 为该函数所接受的形参个数(如果 num_params 为 -1,则该函数可接受任意数量的参数), func 是一个 Python 可调用对象,它将作为 SQL 函数被调用。 如果 deterministic 为真值,则所创建的函数将被标记为 deterministic,这允许 SQLite 执行额外的优化。 此旗标在 SQLite 3.8.3 或更高版本中受到支持,如果在旧版本中使用将引发
NotSupportedError
。此函数可返回任何 SQLite 所支持的类型: bytes, str, int, float 和None
。在 3.8 版更改: 增加了 deterministic 形参。示例:1
2
3
4
5
6
7
8
9
10
11
12
13import 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)创建一个自定义的聚合函数。
参数中 aggregate_class 类必须实现两个方法:
step
和finalize
。step
方法接受 num_params 个参数(如果 num_params 为 -1,那么这个函数可以接受任意数量的参数);finalize
方法返回最终的聚合结果。finalize
方法可以返回任何 SQLite 支持的类型:bytes,str,int,float 和None
。示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22import 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 和 callable 创建排序规则。这个 callable 接受两个字符串对象,如果第一个小于第二个则返回 -1, 如果两个相等则返回 0,如果第一个大于第二个则返回 1。注意,这是用来控制排序的(SQL 中的 ORDER BY),所以它不会影响其它的 SQL 操作。
注意,这个 callable 可调用对象会把它的参数作为 Python 字节串,通常会以 UTF-8 编码格式对它进行编码。
以下示例显示了使用“错误方式”进行排序的自定义排序规则:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20import 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
并设置 callable 参数为None
。1
con.create_collation("reverse", None)
interrupt
()可以从不同的线程调用这个方法来终止所有查询操作,这些查询操作可能正在连接上执行。此方法调用之后, 查询将会终止,而且查询的调用者会获得一个异常。
set_authorizer
(authorizer_callback)此方法注册一个授权回调对象。每次在访问数据库中某个表的某一列的时候,这个回调对象将会被调用。如果要允许访问,则返回
SQLITE_OK
,如果要终止整个 SQL 语句,则返回SQLITE_DENY
,如果这一列需要当做 NULL 值处理,则返回SQLITE_IGNORE
。这些常量可以在sqlite3
模块中找到。回调的第一个参数表示要授权的操作类型。 第二个和第三个参数将是参数或None
,具体取决于第一个参数的值。 第 4 个参数是数据库的名称(“main”,“temp”等),如果需要的话。 第 5 个参数是负责访问尝试的最内层触发器或视图的名称,或者如果此访问尝试直接来自输入 SQL 代码,则为None
。请参阅 SQLite 文档,了解第一个参数的可能值以及第二个和第三个参数的含义,具体取决于第一个参数。 所有必需的常量都可以在sqlite3
模块中找到。set_progress_handler
(handler, n)此例程注册回调。 对SQLite虚拟机的每个多指令调用回调。 如果要在长时间运行的操作期间从SQLite调用(例如更新用户界面),这非常有用。如果要清除以前安装的任何进度处理程序,调用该方法时请将 handler 参数设置为
None
。从处理函数返回非零值将终止当前正在执行的查询并导致它引发OperationalError
异常。set_trace_callback
(trace_callback)为每个 SQLite 后端实际执行的 SQL 语句注册要调用的 trace_callback。传递给回调的唯一参数是正在执行的语句(作为字符串)。 回调的返回值将被忽略。 请注意,后端不仅运行传递给
Cursor.execute()
方法的语句。 其他来源包括 Python 模块的事务管理和当前数据库中定义的触发器的执行。将传入的 trace_callback 设为None
将禁用跟踪回调。enable_load_extension
(enabled)此例程允许/禁止SQLite引擎从共享库加载SQLite扩展。 SQLite扩展可以定义新功能,聚合或全新的虚拟表实现。 一个众所周知的扩展是与SQLite一起分发的全文搜索扩展。
默认情况下禁用可加载扩展。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28import 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()
启用扩展加载。默认情况下禁用可加载扩展。
row_factory
您可以将此属性更改为可接受游标和原始行作为元组的可调用对象,并将返回实际结果行。 这样,您可以实现更高级的返回结果的方法,例如返回一个可以按名称访问列的对象。
示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
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
提供基于索引和不区分大小写的基于名称的访问,几乎没有内存开销。 它可能比您自己的基于字典的自定义方法甚至基于 db_row 的解决方案更好。text_factory
使用此属性可以控制为
TEXT
数据类型返回的对象。 默认情况下,此属性设置为str
和sqlite3
模块将返回TEXT
的 Unicode 对象。 如果要返回字节串,可以将其设置为bytes
。您还可以将其设置为接受单个 bytestring 参数的任何其他可调用对象,并返回结果对象。
请参阅以下示例代码以进行说明:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29import 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文本格式转储数据库的迭代器。 保存内存数据库以便以后恢复时很有用。 此函数提供与 sqlite3 shell 中的 .dump 命令相同的功能。
示例:
1
2
3
4
5
6
7
8# 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=0, progress=None, name=”main”, sleep=0.250*)即使在 SQLite 数据库被其他客户端访问时,或者同时由同一连接访问,该方法也会对其进行备份。 该副本将写入强制参数 target,该参数必须是另一个
Connection
实例。默认情况下,或者当 pages 为
0
或负整数时,整个数据库将在一个步骤中复制;否则该方法一次循环复制 pages 规定数量的页面。示例一,将现有数据库复制到另一个数据库中:
1
2
3
4
5
6
7
8
9
10
11import 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()示例二,将现有数据库复制到临时副本中:
1
2
3
4
5import sqlite3
source = sqlite3.connect('existing_db.db')
dest = sqlite3.connect(':memory:')
source.backup(dest)可用性:SQLite 3.6.11 或以上版本
Cursor 对象
class
sqlite3.Cursor
Cursor
游标实例具有以下属性和方法。execute
(sql[, parameters])执行SQL语句。 可以是参数化 SQL 语句(即,在 SQL 语句中使用占位符)。
sqlite3
模块支持两种占位符:问号(qmark风格)和命名占位符(命名风格)。以下是两种风格的示例:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18import 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()
will only execute a single SQL statement. If you try to execute more than one statement with it, it will raise aWarning
. Useexecutescript()
if you want to execute multiple SQL statements with one call.
executemany
(sql, seq_of_parameters)通过所有参数序列或者映射参数 执行SQL 命令,同时支持使用
iterator
(可迭代对象) yield类型生成参数代替序列。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26import 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 的简短示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17import 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语句。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25import 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()fetchone
()获取查询语句结果中的一条记录集,返回一个单独的序列,当没有数据时返回
None
。fetchmany
(size=cursor.arraysize)提取查询结果的下一组行,返回列表。当没有更多行可用时,将返回一个空列表。每个调用要提取的行数由 [size] 参数指定。如果未提供,则游标的数组大小确定要提取的行数。该方法应尝试提取大小参数指示的行数。如果由于指定的行数不可用而无法这样做,则返回的行数可能更少。请注意,[size] 参数涉及性能注意事项。为了获得最佳性能,通常最好使用数组大小属性。如果使用 [size] 参数,则最好将其保留从
fetchmany()
方法调用到下一个相同的值。
返回list类型存储的所有结果的行。如果没有记录返回,返回一个空的list。
close
()立即关闭游标(无论
__del__
方法是否被调用)。当前游标无法再获取上下文对象,如果尝试访问该游标,则会引发ProgrammingError
异常。rowcount
对于
executemany()
语句,修改次数汇总为rowcount
.根据 Python DB API 规范的要求,rowcount
属性在游标上未执行executeXX()
或最后一个操作的行计数无法由接口决定的情况下为 -1。这包括SELECT
语句,因为我们无法确定在提取所有行之前生成的查询的行数。lastrowid
这是一个只读属性取得最后一条修改记录的rowid。仅当使用
execute()
方法执行INSERT
or aREPLACE
语句时设置该属性。或者 当执行executemany()
方法时,该属性设置为None
。如果INSERT
或REPLACE
语句执行失败时,则返回最近一次成功执行的rowid。arraysize
该属性可读写,主要控制
fetchmany()
方法返回的记录数量。默认值是1意味着返回一行结果。description
此只读属性提供最后一次查询的列名称。为了保持与 Python DB API 的兼容,它为每个列返回一个 7 元组,其中每个元组的最后六个项为
None
.connection
此只读属性提供SQLite数据库的
Connection
使用的游标对象。
行对象
class sqlite3.Row
keys
()该方法返回列名构成的列表。查询后,在
Cursor.description
中元组数据的第一个元素.
接下来我们在上面的例子中初始化一个table:
1 | conn = sqlite3.connect(":memory:") |
我们使用Row
1 | conn.row_factory = sqlite3.Row |
异常
exception
sqlite3.Warning
Exception
的一个子类。exception
sqlite3.Error
此模块中其他异常的基类。 它是
Exception
的一个子类。exception
sqlite3.DatabaseError
抛出和数据库有关异常。
exception
sqlite3.IntegrityError
抛出和关联标识符有关异常,例如外键检查失败,是
DatabaseError
的一个子类。exception
sqlite3.ProgrammingError
抛出和程序有关的异常,例如:table未找到,或已经存在,SQL 语句异常,参数不正确, 是
DatabaseError
的一个子类。exception
sqlite3.OperationalError
抛出和程序无法控制的数据库操作的异常,例如: 不可预料的数据库连接错误,数据源名字未找到,事务没有被执行,是
DatabaseError
的一个子类。exception
sqlite3.NotSupportedError
抛出当一个方法对当前数据库不支持的异常,例如:调用
rollback()
时,数据库事务不支持或者事务被关闭。是DatabaseError
的一个子类
SQLite 与 Python 类型
概述
SQLite 原生支持如下的类型: NULL
,INTEGER
,REAL
,TEXT
,BLOB
。
Python 类型 | SQLite 类型 |
---|---|
None |
NULL |
int |
INTEGER |
float |
REAL |
str |
TEXT |
bytes |
BLOB |
这是SQLite类型默认转换为Python类型的方式:
SQLite 类型 | Python 类型 |
---|---|
NULL |
None |
INTEGER |
int |
REAL |
float |
TEXT |
取决于 text_factory , 默认为 str |
BLOB |
bytes |
sqlite3
中数据类型的扩展有两种途径: 一种是使用SQLite对象适配器扩展附加的Python数据类型;另一种是使用Python类型转换函数转换SQLite类型。
使用适配器在SQLite中存储附加的python数据类型
正如之前描述的转换方法中说明的,SQLite只支持有限的几种数据类型。如果想在SQLite中使用Python的相关数据类型,你必须通过适配器,让SQLite的模块让SQLite支持诸如: one of NoneType, int, float, str, bytes等类型。请看下面的例子:
让对象自行调整
如果自己编写类,这是一种很好的方法。假设有这样的类::
1 | class Point: |
我们想在SQLite中存储,首先选择何种数据类型存储这个Point
类。
接下来使用类方法 __conform__
返回转换后的值, 参数是 PrepareProtocol
类型的protocol
。
1 | import sqlite3 |
注册可调用的适配器
另一个可行的方法时创建一个可以转换string和其他类型的函数,使用register_adapter()
.
1 | import sqlite3 |
对于Python中的内置数据类型 datetime.date
和 datetime.datetime
,我们可以存储 datetime.datetime
使用ISO 实现而非 Unix 时间戳。请参考下面的例子:
1 | import sqlite3 |
将SQLite 值转换为自定义Python 类型
让我们回到刚才定义的Point
类,在SQLite中存储x
,y
字符串类型参数。
首先我们定义一个转换函数,接收字符串类型的参数,转换为Point
类的对象。
转换函数通常处理的是
byte
类型对象,无论你传入的是什么类型 数据。
1 | def convert_point(s): |
现在我们需要让 sqlite3
模块知道你查询的是一个point
对象,有两种方式实现:
- 隐式的声明类型
- 显式的通过列名
1 | import sqlite3 |
默认适配器和转换器
对于时间和 日期时间类型, sqlite模块已经做了自动转换。
下面的示例演示了这一点。
1 | import sqlite3 |
控制事务
默认sqlite3
中对于autocommit
默认是开启的,但是Python中的sqlite3
模块默认并没有开启。
autocommit
模式意味着当修改数据库时对数据库影响立即生效。一个BEGIN
和 SAVEPOINT
的语句禁止automode
,如果是COMMIT
,ROLLBACK
或RELASE
语句执行后,autocommit
模式才设置成启用。
Python sqlite3
默认在DDL 语句( (例如: INSERT
/UPDATE
/DELETE
/REPLACE
).)执行前执行BEGIN
语句。
你可以通过控制 BEGIN
语句,隐式执行connect()
方法的 isolation_level 参数,或是connections的 isolation_level 属性来实现。如果你没有声明 isolation_level,那么使用的就是普通的BEGIN
使用,和DEFERRED
是一样的。其他可能的值还有IMMEDIATE
和 EXCLUSIVE
。
你可以在代码中通过禁止 sqlite3
模块中设定 control the transaction state 的值为BEGIN
, ROLLBACK
, SAVEPOINT
, and RELEASE
语句实现事务处理。
有效使用 sqlite3
使用快捷方式
使用 Connection
对象的非标准 execute()
, executemany()
和 executescript()
方法,可以更简洁地编写代码,因为不必显式创建(通常是多余的) Cursor
对象。相反, Cursor
对象是隐式创建的,这些快捷方法返回游标对象。这样,只需对 Connection
对象调用一次,就能直接执行 SELECT
语句并遍历对象。
1 | import sqlite3 |
通过名称而不是索引访问索引
sqlite3
模块的一个有用功能是内置的 sqlite3.Row
类,该类旨在用作行工厂。
该类的行装饰器可以用索引(如元组)和不区分大小写的名称访问:
1 | import sqlite3 |
使用连接作为上下文管理器
连接对象可以用来作为上下文管理器,它可以自动提交或者回滚事务。如果出现异常,事务会被回滚;否则,事务会被提交。
1 | import sqlite3 |
常见问题
多线程
较老版本的 SQLite 在共享线程之间存在连接问题。这就是Python模块不允许线程之间共享连接和游标的原因。如果仍然尝试这样做,则在运行时会出现异常。
唯一的例外是调用 interrupt()
方法,该方法仅在从其他线程进行调用时才有意义。
关于事务的补充说明
isolation_level
到底控制的是什么,下图摘自SQLite官网。
下面是一个在connect()中不传入 isolation_level的例子:
1 | #!/usr/bin/env python |