SQLite是一个C库,它提供了一个基于磁盘的轻量级数据库,它不需要单独的服务器进程,并允许使用SQL查询语言的非标准变体访问数据库。某些应用程序可以使用SQLite进行内部数据存储。也可以使用SQLite对应用程序进行原型设计,然后将代码移植到更大的数据库,如PostgreSQL或Oracle。

sqlite3模块由GerhardHäring编写。它提供了一个符合DB-API 2.0规范的SQL接口PEP 249

要使用该模块,必须首先创建一个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语句后检索数据,可以将游标视为迭代器,调用游标的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由Marc-AndréLemburg撰写。

模块函数和常量

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 只是列名的第一个单词,即如果你在SQL中使用类似的东西 ,那么我们将解析所有内容,直到列名的第一个空白:列名只是“x”。'as "x [datetime]"'

sqlite3.connectdatabase [timeoutdetect_typesisolation_levelcheck_same_threadfactorycached_statementsuri 
打开与SQLite数据库文件数据库的连接。默认情况下返回一个 Connection对象,除非给出了自定义工厂

database是一个类似路径的对象,它提供要打开的数据库文件的路径名(绝对或相对于当前工作目录)。您可以使用":memory:"打开数据库连接到驻留在RAM而不是磁盘上的数据库。

当多个连接访问数据库,并且其中一个进程修改数据库时,SQLite数据库将被锁定,直到提交该事务为止。该超时参数指定连接应该多长时间等待锁消失,直到引发异常。timeout参数的默认值为5.0(五秒)。

对于isolation_level参数,请参阅对象的 isolation_level属性Connection

SQLite本身仅支持TEXT,INTEGER,REAL,BLOB和NULL类型。如果您想使用其他类型,您必须自己添加对它们的支持。使用模块级函数注册的 detect_types参数和使用自定义转换器register_converter()可以轻松实现。

detect_types缺省值为0(即关闭,无类型检测),可以将其设置为任意组合PARSE_DECLTYPESPARSE_COLNAMES开启类型检测上。

默认情况下,check_same_thread是,True并且只有创建线程可以使用该连接。如果设置False,则可以跨多个线程共享返回的连接。当使用具有相同连接的多个线程时,应由用户序列化写操作以避免数据损坏。

默认情况下,sqlite3模块使用其Connection类进行连接调用。但是,您可以通过为factory 参数提供类来为Connection类创建子类并 connect()使用您的类。

有关详细信息,请参阅本手册的SQLite和Python类型部分。

sqlite3模块在内部使用语句缓存来避免SQL解析开销。如果要显式设置为连接缓存的语句数,可以设置cached_statements参数。当前实现的默认值是缓存100个语句。

如果uri为true,则将数据库解释为URI。这允许您指定选项。例如,要以只读模式打开数据库,您可以使用:

db = sqlite3.connect('file:path/to/database?mode=ro', uri=True)

有关此功能的更多信息,包括已识别选项的列表,可以在SQLite URI文档中找到。

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

版本3.7中已更改:数据库现在也可以是类似路径的对象,而不仅仅是字符串。

sqlite3.register_convertertypenamecallable 
注册callable以将数据库中的bytestring转换为自定义Python类型。将为typename类型的所有数据库值调用callable 。赋予 函数的参数detect_typesconnect()进行类型检测的工作方式。请注意,查询中的typename和类型名称以不区分大小写的方式匹配。
sqlite3.register_adapter类型可调用
注册callable以将自定义Python 类型转换为SQLite支持的类型之一。可调用的callable接受Python值作为单个参数,并且必须返回以下类型的值:int,float,str或bytes。
sqlite3.complete_statementsql 
返回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()

 

sqlite3.enable_callback_tracebacks
默认情况下,您不会在用户定义的函数,聚合,转换器,授权器回调等中获得任何回溯。如果要调试它们,可以在标志设置为的情况下调用此函数True。之后,您将从回调中获得追溯sys.stderr。用于False再次禁用该功能。

连接对象

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

isolation_level
获取或设置当前的默认隔离级别。None用于自动提交模式或“DEFERRED”,“IMMEDIATE”或“EXCLUSIVE”之一。有关更详细的说明,请参阅控制事务一节 。
in_transaction
True如果事务处于活动状态(存在未提交的更改), False否则。只读属性。

版本3.2中的新功能。

cursorfactory = Cursor 
cursor方法接受单个可选参数factory。如果提供,则必须是可调用的,返回实例Cursor 或其子类。
commit
此方法提交当前事务。如果不调用此方法,则自上次调用以来执行的任何操作commit()都不会从其他数据库连接中看到。如果您想知道为什么没有看到您写入数据库的数据,请检查您是否忘记调用此方法。
rollback
此方法回滚自上次调用以来对数据库的任何更改 commit()
close
这将关闭数据库连接。请注意,这不会自动调用commit()。如果您只是先关闭数据库连接而不commit()先打电话,那么您的更改将会丢失!
executesql [参数
这是一个非标准的快捷方式,它通过调用cursor()方法创建游标对象,execute()使用给定的参数调用游标的 方法,然后返回游标。
executemanysql [参数
这是一个非标准的快捷方式,它通过调用cursor()方法创建游标对象,executemany()使用给定的参数调用游标的 方法,然后返回游标。
executescriptsql_script 
这是一个非标准的快捷方式,它通过调用cursor()方法创建游标对象,executescript()使用给定的sql_script调用游标的 方法,并返回游标。
create_functionnamenum_paramsfunc 
创建一个可以从SQL语句中以后使用下面的功能名称的用户定义函数的名称num_params是函数接受的参数数量(如果num_params为-1,则函数可以使用任意数量的参数),func是Python可调用的,称为SQL函数。

该函数可以返回SQLite支持的任何类型:bytes,str,int,float和None

例:

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

 

create_aggregatenamenum_paramsaggregate_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])

 

create_collation名称可调用
创建具有指定名称可调用的排序规则。callable将传递两个字符串参数。如果第一个排序低于第二个,则应返回-1;如果排序等于0,则返回0;如果第一个排序高于第二个,则返回1。请注意,这会控制排序(SQL中的ORDER BY),因此您的比较不会影响其他SQL操作。

请注意,callable将其参数作为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使用Noneas callable调用:

con.create_collation("reverse", None)

 

interrupt
您可以从其他线程调用此方法以中止可能在连接上执行的任何查询。然后查询将中止,调用者将获得异常。
set_authorizerauthorizer_callback 
此例程注册回调。每次尝试访问数据库中表的列时都会调用回调。SQLITE_OK如果允许访问,则应返回回调 ,SQLITE_DENY如果整个SQL语句应该中止并出现错误,SQLITE_IGNORE并且该列应被视为NULL值。这些常量在sqlite3模块中可用 。

回调的第一个参数表示要授权的操作类型。第二个和第三个参数将是参数或None 取决于第一个参数。第四个参数是数据库的名称(“main”,“temp”等)(如果适用)。第五个参数是负责访问尝试的最内层触发器或视图的名称,或者 None此访问尝试是否直接来自输入SQL代码。

请参阅SQLite文档,了解第一个参数的可能值以及第二个和第三个参数的含义,具体取决于第一个参数。sqlite3模块中提供了所有必需的常量。

set_progress_handler处理程序
此例程注册回调。 对SQLite虚拟机的每n个指令调用回调。如果要在长时间运行的操作期间从SQLite调用(例如更新GUI),这非常有用。

如果要清除以前安装的任何进度处理程序,请使用Nonefor handler调用该方法。

从处理函数返回非零值将终止当前正在执行的查询并导致它引发OperationalError 异常。

set_trace_callbacktrace_callback 
注册要为SQLite后端实际执行的每个SQL语句调用trace_callback

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

传递Nonetrace_callback将禁用跟踪回调。

版本3.3中的新功能。

enable_load_extension启用
此例程允许/禁止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)

 

load_extension路径
此例程从共享库加载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"])

 

如果返回元组是不够的,并且您希望对列进行基于名称的访问,则应考虑设置row_factory为高度优化的sqlite3.Row类型。Row提供基于索引和不区分大小写的基于名称的访问,几乎没有内存开销。它可能比您自己的基于字典的自定义方法甚至基于db_row的解决方案更好。

text_factory
使用此属性可以控制为TEXT 数据类型返回的对象。默认情况下,此属性设置为str, sqlite3模块将返回Unicode对象TEXT。如果要返回字节串,可以将其设置为bytes

您还可以将其设置为接受单个bytestring参数的任何其他可调用对象,并返回结果对象。

请参阅以下示例代码以进行说明:

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"

 

total_changes
返回自打开数据库连接以来已修改,插入或删除的数据库行的总数。
iterdump
返回以SQL文本格式转储数据库的迭代器。保存内存数据库以便以后恢复时很有用。此函数提供与sqlite3shell中的.dump命令相同的功能。

例:

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

 

backuptarget*pages = 0progress = Nonename =“main”sleep = 0.250 
即使在SQLite数据库被其他客户端访问时,或者同时由同一连接访问,该方法也会对其进行备份。副本将写入强制参数目标,该目标必须是另一个 Connection实例。

默认情况下,或者当页面0负整数或整数时,整个数据库将在一个步骤中复制; 否则,该方法一次执行循环复制到页面页面。

如果指定了progress,则它必须是None或者是在每次迭代时将使用三个整数参数执行的可调用对象,分别是最后一次迭代的状态,仍然要复制的剩余页数以及页数。

参数指定将要复制的数据库名:它必须包含一个字符串"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')
with sqlite3.connect('backup.db') as bck:
    con.backup(bck, pages=1, progress=progress)

 

示例2,将现有数据库复制到临时副本中:

import sqlite3

source = sqlite3.connect('existing_db.db')
dest = sqlite3.connect(':memory:')
source.backup(dest)

 

可用性:SQLite 3.6.11或更高版本

版本3.7中的新功能。

游标对象

sqlite3.Cursor
一个Cursor实例具有以下属性和方法。

executesql [参数
执行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())

 

execute()只会执行一个SQL语句。如果你试图用它执行多个语句,它将引发一个Warning。使用executescript(),如果你想用一个调用执行多个SQL语句。

executemanysqlseq_of_parameters 
对序列seq_of_parameters中的所有参数序列或映射执行SQL命令。该sqlite3模块还允许使用迭代器产生参数而不是序列。

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

 

这是使用生成器的简短示例:

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

 

executescriptsql_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
    );
    """)

 

fetchone
获取查询结果集的下一行,返回单个序列,或者None当没有更多数据可用时。
fetchmanysize = cursor.arraysize 
获取查询结果的下一组行,返回一个列表。没有更多行可用时返回空列表。

每次调用获取的行数由size参数指定。如果没有给出,则游标的arraysize确定要获取的行数。该方法应尝试获取size参数指示的行数。如果由于指定的行数不可用而无法执行此操作,则可能会返回更少的行。

请注意,size参数涉及性能考虑因素。为获得最佳性能,通常最好使用arraysize属性。如果使用size参数,那么最好从一次fetchmany()调用到下一次调用保留相同的值。

fetchall
获取查询结果的所有(剩余)行,返回列表。请注意,游标的arraysize属性可能会影响此操作的性能。没有可用行时返回空列表。
close
现在关闭光标(而不是每次__del__调用时)。

从这一点开始,光标将无法使用; 一ProgrammingError ,如果任何操作试图用光标将引发异常。

rowcount
虽然模块的Cursorsqlite3实现了这个属性,但数据库引擎自己支持确定“受影响的行”/“选择的行”是古怪的。

对于executemany()陈述,修改的数量总结为rowcount

根据Python DB API Spec的要求,rowcount如果没有executeXX()对游标执行或者最后一个操作的rowcount不能被接口确定,则属性“为-1 ”。这包括SELECT 语句,因为在获取所有行之前,我们无法确定查询生成的行数。

对于3.6.5之前的SQLite版本,rowcount如果您没有任何条件,则设置为0 。DELETE FROM table

lastrowid
此只读属性提供上次修改行的rowid。仅当您使用该方法发出INSERTREPLACE声明 时才设置它execute()。比其他操作INSERT或 REPLACE或者当executemany()被调用时,lastrowid被设置为None

如果INSERTor REPLACE语句未能插入,则返回先前成功的rowid。

版本3.6中已更改:添加了对REPLACE语句的支持。

arraysize
读/写属性,用于控制返回的行数fetchmany()。默认值为1,表示每次调用将获取一行。
description
此只读属性提供上次查询的列名称。为了与Python DB API保持兼容,它为每个列返回一个7元组,其中每个元组的最后六个项是None

它是为SELECT没有任何匹配行的语句设置的。

connection
此只读属性提供对象Connection 使用的SQLite数据库Cursor。一个Cursor通过调用创建的对象con.cursor()将有一个 connection引用属性CON

>>>
>>> con = sqlite3.connect(":memory:")
>>> cur = con.cursor()
>>> cur.connection == con
True

 

行对象

sqlite3.Row
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
例外

 

异常sqlite3.Warning
的子类Exception
异常sqlite3.Error
此模块中其他异常的基类。它是的子类Exception
异常sqlite3.DatabaseError
针对与数据库相关的错误引发异常。
异常sqlite3.IntegrityError
当数据库的关系完整性受到影响时引发异常,例如外键检查失败。它是的子类DatabaseError
异常sqlite3.ProgrammingError
针对编程错误引发的异常,例如表未找到或已经存在,SQL语句中的语法错误,指定的参数数量错误等等。它是。的子类DatabaseError
异常sqlite3.OperationalError
针对与数据库操作相关的错误引发异常,并且不一定在程序员的控制之下,例如发生意外断开,找不到数据源名称,无法处理事务等。它是。的子类DatabaseError
异常sqlite3.NotSupportedError
如果使用数据库不支持的方法或数据库API,例如rollback() 在不支持事务的连接上调用方法或关闭事务,则会引发异常。它是的子类DatabaseError

SQLite和Python类型

介绍

SQLite的原生支持以下几种类型:NULLINTEGER, REALTEXTBLOB

因此可以将以下Python类型发送到SQLite而不会出现任何问题:

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模块的类型系统可以通过两种方式扩展:您可以通过对象自适应将其他Python类型存储在SQLite数据库中,您可以让sqlite3模块通过转换器将SQLite类型转换为不同的Python类型。

使用适配器在SQLite数据库中存储其他Python类型

如前所述,SQLite本身仅支持一组有限的类型。要在SQLite中使用其他Python类型,必须使它们适应 SQLite 的sqlite3模块支持的类型之一: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])

 

注册可调用的适配器

另一种可能性是创建一个函数,将类型转换为字符串表示并注册函数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])

 

sqlite3模块有两个默认适配器,用于Python的内置 datetime.datedatetime.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])

 

SQLite值转换为自定义Python类型

编写适配器允许您将自定义Python类型发送到SQLite。但为了使它真正有用,我们需要使Python到SQLite到Python的往返工作。

输入转换器。

我们回到Point课堂吧。我们存储了x和y坐标,这些坐标通过分号分隔为SQLite中的字符串。

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

注意

无论您将值发送到SQLite的哪种数据类型,都始终使用bytes对象调用转换器函数。

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

默认转换器在名称“date”下注册,名称为 datetime.date“timestamp” 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]))

 

如果存储在SQLite中的时间戳具有长于6个数字的小数部分,则其值将被时间戳转换器截断为微秒精度。

控制交易

默认情况下,底层sqlite3库以autocommit模式运行,但默认情况下Python sqlite3模块不运行。

autocommitmode表示修改数据库的语句立即生效。一个BEGINSAVEPOINT语句禁用autocommit 模式,a COMMIT,a ROLLBACK或a RELEASE结束最外面的事务,重新打开autocommit模式。

sqlite3默认情况下,Python 模块BEGIN在数据修改语言(DML)语句(即INSERTUPDATEDELETEREPLACE)之前隐式发出语句 。

您可以通过对 调用的isolation_level参数或通过连接的属性来控制隐式执行哪种BEGIN语句。如果未指定isolation_level,则使用plain ,这相当于指定。其他可能的值是 和。sqlite3connect()isolation_levelBEGINDEFERREDIMMEDIATEEXCLUSIVE

您可以sqlite3通过设置isolation_level为禁用模块的隐式事务管理None。这将使底层 sqlite3库以autocommit模式运行。然后,您可以完全明确地发出控制交易状态BEGINROLLBACK, 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")

 

按名称而不是按索引访问列

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"]

 

使用连接作为上下文管理器

连接对象可以用作自动提交或回滚事务的上下文管理器。如果发生异常,则回滚事务; 否则,交易承诺:

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

 

常见问题

多线程

较旧的SQLite版本在线程之间共享连接存在问题。这就是Python模块不允许在线程之间共享连接和游标的原因。如果您仍然尝试这样做,您将在运行时获得异常。

唯一的例外是调用interrupt()方法,只有从不同的线程调用才有意义。

脚注

[1] 12sqlite3的模块没有默认装载的扩展支持内置,因为一些平台(特别是Mac OS X的)具有被没有这个功能编译SQLite的库。要获得可加载的扩展支持,必须通过-enable-loadable-sqlite-extensions进行配置。