SQLite Python
最后修改于 2020 年 7 月 6 日
本教程已被 Python SQLite 教程取代。
这是一个针对 SQLite 数据库的 Python 编程教程。它涵盖了使用 Python 语言进行 SQLite 编程的基础知识。你可能还想查看 ZetCode 上的 Python 教程、SQLite 教程、MySQL Python 教程 或 PostgreSQL Python 教程。
要学习本教程,我们必须在系统上安装 Python 语言、SQLite 数据库、pysqlite
语言绑定和 sqlite3
命令行工具。
如果我们有 Python 2.5+,那么我们只需要安装 sqlite3
命令行工具。SQLite 库和 pysqlite
语言绑定都内置在 Python 语言中。
$ python2 Python 2.7.12 (default, Nov 12 2018, 14:36:49) [GCC 5.4.0 20160609] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> import sqlite3 >>> sqlite3.version '2.6.0' >>> sqlite3.sqlite_version '3.16.2'
在 shell 中,我们启动 Python 交互式解释器。我们可以看到 Python 版本。在本例中,它是 Python 2.7.12。sqlite.version
是 pysqlite
的版本 (2.6.0),它是 Python 语言到 SQLite 数据库的绑定。sqlite3.sqlite_version
给出了 SQLite 数据库库的版本。在本例中,版本是 3.16.2。
SQLite
SQLite 是一个嵌入式关系型数据库引擎。文档称它为一个自包含、无服务器、零配置和事务性 SQL 数据库引擎。它非常流行,全球有数亿份正在使用中。包括 Python 和 PHP 在内的几种编程语言都内置支持 SQLite。
创建 SQLite 数据库
现在我们将使用 sqlite3
命令行工具创建一个新数据库。
$ sqlite3 test.db SQLite version 3.16.2 2017-01-06 16:32:41 Enter ".help" for usage hints. sqlite>
我们向 sqlite3
工具提供一个参数;test.db
是一个数据库名称。它是我们磁盘上的一个文件。如果它存在,它将被打开。如果不存在,它将被创建。
sqlite> .tables sqlite> .exit $ ls test.db
.tables
命令给出 test.db 数据库中的表列表。目前没有表。.exit
命令终止 sqlite3 命令行工具的交互式会话。ls
Unix 命令显示当前工作目录的内容。我们可以看到 test.db
文件。所有数据都将存储在这个文件中。
SQLite 版本示例
在第一个代码示例中,我们将获取 SQLite 数据库的版本。
#!/usr/bin/env python2 # -*- coding: utf-8 -*- import sqlite3 as lite import sys con = None try: con = lite.connect('test.db') cur = con.cursor() cur.execute('SELECT SQLITE_VERSION()') data = cur.fetchone()[0] print "SQLite version: {}".format(data) except lite.Error, e: print "Error {}:".format(e.args[0]) sys.exit(1) finally: if con: con.close()
在上面的 Python 脚本中,我们连接到之前创建的 test.db
数据库。我们执行一个 SQL 语句,它返回 SQLite 数据库的版本。
import sqlite3 as lite
sqlite3
模块用于操作 SQLite 数据库。
con = None
我们将 con
变量初始化为 None。如果我们无法创建数据库连接(例如磁盘已满),我们将不会定义连接变量。这将导致 finally 子句中出现错误。
con = lite.connect('test.db')
在这里我们连接到 test.db
数据库。connect
方法返回一个连接对象。
cur = con.cursor() cur.execute('SELECT SQLITE_VERSION()')
从连接中,我们获取游标对象。游标用于遍历结果集中的记录。我们调用游标的 execute
方法并执行 SQL 语句。
data = cur.fetchone()[0]
我们获取数据。由于我们只检索一条记录,我们调用 fetchone
方法。
print "SQLite version: {}".format(data)
我们将检索到的数据打印到控制台。
except lite.Error, e: print "Error {}:".format(e.args[0]) sys.exit(1)
如果发生异常,我们打印错误消息并以错误代码 1 退出脚本。
finally: if con: con.close()
在最后一步,我们释放资源。
在第二个示例中,我们再次获取 SQLite 数据库的版本。这次我们将使用 with
关键字。
#!/usr/bin/env python2 # -*- coding: utf-8 -*- import sqlite3 as lite con = lite.connect('test.db') with con: cur = con.cursor() cur.execute('SELECT SQLITE_VERSION()') data = cur.fetchone()[0] print "SQLite version: {}".format(data)
该脚本返回 SQLite 数据库的当前版本。使用 with
关键字,代码更加紧凑。
with con:
使用 with
关键字,Python 解释器会自动释放资源。它还提供错误处理。
$ ./version2.py SQLite version: 3.16.2
这是输出。
SQLite Python 创建表
我们创建一个 cars
表并插入几行。
#!/usr/bin/env python2 # -*- coding: utf-8 -*- import sqlite3 as lite con = lite.connect('test.db') with con: cur = con.cursor() cur.execute("CREATE TABLE cars(id INT, name TEXT, price INT)") cur.execute("INSERT INTO cars VALUES(1,'Audi',52642)") cur.execute("INSERT INTO cars VALUES(2,'Mercedes',57127)") cur.execute("INSERT INTO cars VALUES(3,'Skoda',9000)") cur.execute("INSERT INTO cars VALUES(4,'Volvo',29000)") cur.execute("INSERT INTO cars VALUES(5,'Bentley',350000)") cur.execute("INSERT INTO cars VALUES(6,'Citroen',21000)") cur.execute("INSERT INTO cars VALUES(7,'Hummer',41400)") cur.execute("INSERT INTO cars VALUES(8,'Volkswagen',21600)")
上面的脚本创建了一个 cars
表并向其中插入了 8 行。
cur.execute("CREATE TABLE cars(id INT, name TEXT, price INT)")
此 SQL 语句创建一个新的 cars
表。该表有三列。
cur.execute("INSERT INTO cars VALUES(1,'Audi',52642)") cur.execute("INSERT INTO cars VALUES(2,'Mercedes',57127)")
这两行将两辆车插入到表中。使用 with
关键字,更改会自动提交。否则,我们必须手动提交它们。
sqlite> .mode column sqlite> .headers on
我们使用 sqlite3
工具来验证写入的数据。首先,我们修改数据在控制台中的显示方式。我们使用列模式并打开表头。
sqlite> select * from cars; id name price ---------- ---------- ---------- 1 Audi 52642 2 Mercedes 57127 3 Skoda 9000 4 Volvo 29000 5 Bentley 350000 6 Citroen 21000 7 Hummer 41400 8 Volkswagen 21600
这是我们写入 cars
表的数据。
我们将创建相同的表。这次使用方便的 executemany
方法。
#!/usr/bin/env python2 # -*- coding: utf-8 -*- import sqlite3 as lite cars = ( (1, 'Audi', 52642), (2, 'Mercedes', 57127), (3, 'Skoda', 9000), (4, 'Volvo', 29000), (5, 'Bentley', 350000), (6, 'Hummer', 41400), (7, 'Volkswagen', 21600) ) con = lite.connect('test.db') with con: cur = con.cursor() cur.execute("DROP TABLE IF EXISTS cars") cur.execute("CREATE TABLE cars(id INT, name TEXT, price INT)") cur.executemany("INSERT INTO cars VALUES(?, ?, ?)", cars)
如果 cars
表存在,程序会删除它并重新创建。
cur.execute("DROP TABLE IF EXISTS cars") cur.execute("CREATE TABLE cars(id INT, name TEXT, price INT)")
第一个 SQL 语句删除(如果存在)cars 表。第二个 SQL 语句创建 cars 表。
cur.executemany("INSERT INTO cars VALUES(?, ?, ?)", cars)
我们使用方便的 executemany
方法向表中插入 8 行。该方法的第一个参数是一个参数化的 SQL 语句。第二个参数是数据,以元组的元组形式。
我们提供另一种创建 cars
表的方式。我们手动提交更改并提供自己的错误处理。
#!/usr/bin/env python2 # -*- coding: utf-8 -*- import sqlite3 as lite import sys try: con = lite.connect('test.db') cur = con.cursor() cur.executescript(""" DROP TABLE IF EXISTS cars; CREATE TABLE cars(id INT, name TEXT, price INT); INSERT INTO cars VALUES(1,'Audi',52642); INSERT INTO cars VALUES(2,'Mercedes',57127); INSERT INTO cars VALUES(3,'Skoda',9000); INSERT INTO cars VALUES(4,'Volvo',29000); INSERT INTO cars VALUES(5,'Bentley',350000); INSERT INTO cars VALUES(6,'Citroen',21000); INSERT INTO cars VALUES(7,'Hummer',41400); INSERT INTO cars VALUES(8,'Volkswagen',21600); """) con.commit() except lite.Error, e: if con: con.rollback() print "Error {}:".format(e.args[0]) sys.exit(1) finally: if con: con.close()
在上面的脚本中,我们使用 executescript
方法(重新)创建 cars
表。
cur.executescript(""" DROP TABLE IF EXISTS cars; CREATE TABLE cars(id INT, name TEXT, price INT); INSERT INTO cars VALUES(1,'Audi',52642); INSERT INTO cars VALUES(2,'Mercedes',57127); ...
executescript
方法允许我们一步执行整个 SQL 代码。
con.commit()
如果没有 with
关键字,则必须使用 commit
方法提交更改。
except lite.Error, e: if con: con.rollback() print "Error {}:".format(e.args[0]) sys.exit(1)
如果出现错误,更改将被回滚并向终端打印错误消息。
SQLite Python lastrowid
有时,我们需要确定最后插入行的 ID。在 Python SQLite 中,我们使用游标对象的 lastrowid
属性。
#!/usr/bin/env python2 # -*- coding: utf-8 -*- import sqlite3 as lite con = lite.connect(':memory:') with con: cur = con.cursor() cur.execute("CREATE TABLE friends(id INTEGER PRIMARY KEY, name TEXT);") cur.execute("INSERT INTO friends(name) VALUES ('Tom');") cur.execute("INSERT INTO friends(name) VALUES ('Rebecca');") cur.execute("INSERT INTO friends(name) VALUES ('Jim');") cur.execute("INSERT INTO friends(name) VALUES ('Robert');") last_row_id = cur.lastrowid print "The last Id of the inserted row is {}".format(last_row_id)
我们在内存中创建了一个 friends
表。ID 会自动递增。
cur.execute("CREATE TABLE friends(id INTEGER PRIMARY KEY, name TEXT);")
在 SQLite 中,INTEGER PRIMARY KEY
列是自动递增的。还有一个 AUTOINCREMENT
关键字。当用于 INTEGER PRIMARY KEY AUTOINCREMENT
时,将使用略有不同的 ID 创建算法。
cur.execute("INSERT INTO friends(name) VALUES ('Tom');") cur.execute("INSERT INTO friends(name) VALUES ('Rebecca');") cur.execute("INSERT INTO friends(name) VALUES ('Jim');") cur.execute("INSERT INTO friends(name) VALUES ('Robert');")
使用自动递增时,我们必须明确说明列名,省略自动递增的列。这四个语句将四行插入 friends
表。
last_row_id = cur.lastrowid
使用 lastrowid
,我们获取最后插入的行 ID。
$ ./lastrowid.py The last Id of the inserted row is 4
我们看到了程序的输出。
SQLite Python 检索数据
现在我们已经向数据库中插入了一些数据,我们想将其取回。
#!/usr/bin/env python2 # -*- coding: utf-8 -*- import sqlite3 as lite con = lite.connect('test.db') with con: cur = con.cursor() cur.execute("SELECT * FROM cars") rows = cur.fetchall() for row in rows: print row
在这个例子中,我们从 cars
表中检索所有数据。
cur.execute("SELECT * FROM cars")
此 SQL 语句从 cars
表中选择所有数据。
rows = cur.fetchall()
fetchall
方法获取所有记录。它返回一个结果集。从技术上讲,它是一个元组的元组。每个内部元组代表表中的一行。
for row in rows: print row
我们将数据逐行打印到控制台。
$ ./select_all.py (1, u'Audi', 52642) (2, u'Mercedes', 57127) (3, u'Skoda', 9000) (4, u'Volvo', 29000) (5, u'Bentley', 350000) (6, u'Citroen', 21000) (7, u'Hummer', 41400) (8, u'Volkswagen', 21600)
这是示例的输出。
一次返回所有数据可能不可行。我们可以逐行获取。
#!/usr/bin/env python2 # -*- coding: utf-8 -*- import sqlite3 as lite con = lite.connect('test.db') with con: cur = con.cursor() cur.execute("SELECT * FROM cars") while True: row = cur.fetchone() if row == None: break print row[0], row[1], row[2]
在这个脚本中,我们连接到数据库并逐行获取 cars
表的行。
while True:
我们从 while 循环访问数据。当我们读取最后一行时,循环终止。
row = cur.fetchone() if row == None: break
fetchone
方法返回表中的下一行。如果没有更多数据,它返回 None
。在这种情况下,我们中断循环。
print row[0], row[1], row[2]
数据以元组的形式返回。在这里我们从元组中选择记录。第一个是 ID,第二个是汽车名称,第三个是汽车价格。
$ ./fetch_one.py 1 Audi 52642 2 Mercedes 57127 3 Skoda 9000 4 Volvo 29000 5 Bentley 350000 6 Citroen 21000 7 Hummer 41400 8 Volkswagen 21600
这是示例的输出。
SQLite Python 字典游标
默认游标以元组的元组形式返回数据。当我们使用字典游标时,数据以 Python 字典的形式发送。这样我们就可以通过列名来引用数据。
#!/usr/bin/env python2 # -*- coding: utf-8 -*- import sqlite3 as lite con = lite.connect('test.db') with con: con.row_factory = lite.Row cur = con.cursor() cur.execute("SELECT * FROM cars") rows = cur.fetchall() for row in rows: print "{} {} {}".format(row["id"], row["name"], row["price"])
在这个例子中,我们使用字典游标打印 cars
表的内容。
con.row_factory = lite.Row
我们选择一个字典游标。现在我们可以通过列名访问记录。
for row in rows: print "{} {} {}".format(row["id"], row["name"], row["price"])
数据通过列名访问。
SQLite Python 参数化查询
现在我们将关注参数化查询。当我们使用参数化查询时,我们使用占位符而不是直接将值写入语句。参数化查询提高了安全性和性能。
Python sqlite3
模块支持两种类型的占位符:问号和命名占位符。
#!/usr/bin/env python2 # -*- coding: utf-8 -*- import sqlite3 as lite uId = 1 uPrice = 62300 con = lite.connect('test.db') with con: cur = con.cursor() cur.execute("UPDATE cars SET price=? WHERE id=?", (uPrice, uId)) print "Number of rows updated: {}".format(cur.rowcount)
我们更新一辆汽车的价格。在这个代码示例中,我们使用问号占位符。
cur.execute("UPDATE cars SET price=? WHERE id=?", (uPrice, uId))
问号 ?
是值的占位符。值被添加到占位符中。
print "Number of rows updated: {}".format(cur.rowcount)
rowcount
属性返回更新的行数。在我们的例子中,更新了一行。
第二个示例使用带有命名占位符的参数化语句。
#!/usr/bin/env python2 # -*- coding: utf-8 -*- import sqlite3 as lite uId = 4 con = lite.connect('test.db') with con: cur = con.cursor() cur.execute("SELECT name, price FROM cars WHERE Id=:Id", {"Id": uId}) row = cur.fetchone() print row[0], row[1]
我们使用命名占位符选择汽车的名称和价格。
cur.execute("SELECT name, price FROM cars WHERE Id=:Id", {"Id": uId})
命名占位符以冒号字符开头。
SQLite Python 插入图片
在本节中,我们将向 SQLite 数据库插入图片。请注意,有些人反对将图片放入数据库。在这里我们只展示如何操作。我们不深入探讨是否将图片保存在数据库中的技术问题。
sqlite> CREATE TABLE images(id INTEGER PRIMARY KEY, data BLOB);
在这个例子中,我们创建一个名为 Images 的新表。对于图片,我们使用 BLOB
数据类型,它代表二进制大对象。
#!/usr/bin/env python2 # -*- coding: utf-8 -*- import sqlite3 as lite import sys def readImage(): fin = None try: fin = open("sid.png", "rb") img = fin.read() return img except IOError, e: print e sys.exit(1) finally: if fin: fin.close() try: con = lite.connect('test.db') cur = con.cursor() data = readImage() binary = lite.Binary(data) cur.execute("INSERT INTO images(data) VALUES (?)", (binary,) ) con.commit() except lite.Error, e: if con: con.rollback() print e sys.exit(1) finally: if con: con.close()
在这个脚本中,我们从当前工作目录读取一张图片,并将其写入 SQLite test.db
数据库的 images
表中。
try: fin = open("sid.png", "rb") img = fin.read() return img
我们从文件系统读取二进制数据。我们有一个名为 sid.png
的 JPG 图片。
binary = lite.Binary(data)
数据使用 SQLite Binary
对象进行编码。
cur.execute("INSERT INTO images(data) VALUES (?)", (binary,) )
这个 SQL 语句用于将图像插入数据库。
SQLite Python 读取图片
在本节中,我们将执行反向操作:我们从数据库表中读取图片。
#!/usr/bin/env python2 # -*- coding: utf-8 -*- import sqlite3 as lite import sys def writeImage(data): fout = None try: fout = open('sid2.png','wb') fout.write(data) except IOError, e: print e sys.exit(1) finally: if fout: fout.close() try: con = lite.connect('test.db') cur = con.cursor() cur.execute("SELECT data FROM images LIMIT 1") data = cur.fetchone()[0] writeImage(data) except lite.Error, e: print e sys.exit(1) finally: if con: con.close()
我们从 Images
表中读取图像数据,并将其写入另一个文件,我们称之为 woman2.jpg
。
try: fout = open('sid2.png','wb') fout.write(data)
我们以写入模式打开一个二进制文件。来自数据库的数据将被写入该文件。
cur.execute("SELECT data FROM images LIMIT 1") data = cur.fetchone()[0]
这两行从 images
表中选择并获取数据。我们从第一行获取二进制数据。
SQLite Python 元数据
元数据是关于数据库中数据的信息。SQLite 中的元数据包含关于表和列的信息,我们存储数据。受 SQL 语句影响的行数是元数据。结果集中返回的行数和列数也属于元数据。
SQLite 中的元数据可以使用 PRAGMA
命令获取。SQLite 对象可能具有属性,这些属性就是元数据。最后,我们还可以通过查询 SQLite 系统表 sqlite_master
来获取特定的元数据。
#!/usr/bin/env python2 # -*- coding: utf-8 -*- import sqlite3 as lite con = lite.connect('test.db') with con: cur = con.cursor() cur.execute('PRAGMA table_info(cars)') data = cur.fetchall() for d in data: print d[0], d[1], d[2]
在这个例子中,我们发出 PRAGMA table_info(tableName)
命令,以获取有关我们 cars
表的一些元数据信息。
cur.execute('PRAGMA table_info(cars)')
PRAGMA table_info(tableName)
命令为 cars
表中的每一列返回一行。结果集中的列包括列顺序号、列名、数据类型、列是否可以为 NULL
,以及列的默认值。
for d in data: print d[0], d[1], d[2]
根据提供的信息,我们打印列顺序号、列名和列数据类型。
$ ./column_names.py 0 id INT 1 name TEXT 2 price INT
示例的输出。
接下来我们将打印 cars
表中的所有行及其列名。
#!/usr/bin/env python2 # -*- coding: utf-8 -*- import sqlite3 as lite con = lite.connect('test.db') with con: cur = con.cursor() cur.execute('SELECT * FROM cars') col_names = [cn[0] for cn in cur.description] rows = cur.fetchall() print "{:3} {:10} {:7}".format(col_names[0], col_names[1], col_names[2]) for row in rows: print "{:<3} {:<10} {:7}".format(row[0], row[1], row[2])
我们将 cars
表的内容打印到控制台。现在,我们也包含了列名。记录与列名对齐。
col_names = [cn[0] for cn in cur.description]
我们从游标对象的 description
属性获取列名。
print "{:3} {:10} {:7}".format(col_names[0], col_names[1], col_names[2])
这一行打印了 cars
表的三个列名。
for row in rows: print "{:<3} {:<10} {:7}".format(row[0], row[1], row[2])
我们使用 for 循环打印行。数据与列名对齐。
$ ./column_names2.py id name price 1 Audi 62300 2 Mercedes 57127 3 Skoda 9000 4 Volvo 29000 5 Bentley 350000 6 Hummer 41400 7 Volkswagen 21600
这是输出。
在与元数据相关的最后一个示例中,我们将列出 test.db
数据库中的所有表。
#!/usr/bin/env python2 # -*- coding: utf-8 -*- import sqlite3 as lite con = lite.connect('test.db') with con: cur = con.cursor() cur.execute("SELECT name FROM sqlite_master WHERE type='table'") rows = cur.fetchall() for row in rows: print row[0]
该代码示例将当前数据库中所有可用的表打印到终端。
cur.execute("SELECT name FROM sqlite_master WHERE type='table'")
表名存储在系统表 sqlite_master
中。
$ ./list_tables.py cars images
这些是我们系统上的表。
SQLite Python 数据导出与导入
我们可以将数据以 SQL 格式转储,以创建数据库表的简单备份。
#!/usr/bin/env python2 # -*- coding: utf-8 -*- import sqlite3 as lite cars = ( (1, 'Audi', 52643), (2, 'Mercedes', 57642), (3, 'Skoda', 9000), (4, 'Volvo', 29000), (5, 'Bentley', 350000), (6, 'Hummer', 41400), (7, 'Volkswagen', 21600) ) def writeData(data): f = open('cars.sql', 'w') with f: f.write(data) con = lite.connect(':memory:') with con: cur = con.cursor() cur.execute("DROP TABLE IF EXISTS cars") cur.execute("CREATE TABLE cars(id INT, name TEXT, price INT)") cur.executemany("INSERT INTO cars VALUES(?, ?, ?)", cars) cur.execute("DELETE FROM cars WHERE price < 30000") data = '\n'.join(con.iterdump()) writeData(data)
在上面的示例中,我们在内存中重新创建了 cars
表。我们从表中删除了一些行,并将表的当前状态转储到 cars.sql
文件中。此文件可以作为表的当前备份。
def writeData(data): f = open('cars.sql', 'w') with f: f.write(data)
表中的数据正在写入文件。
con = lite.connect(':memory:')
我们在内存中创建了一个临时表。
cur.execute("DROP TABLE IF EXISTS cars") cur.execute("CREATE TABLE cars(id INT, name TEXT, price INT)") cur.executemany("INSERT INTO cars VALUES(?, ?, ?)", cars) cur.execute("DELETE FROM cars WHERE price < 30000")
这些行创建了一个 cars
表,插入值并删除 price
小于 30000 单位的行。
data = '\n'.join(con.iterdump())
con.iterdump
返回一个迭代器,用于以 SQL 文本格式转储数据库。内置的 join
函数接受迭代器并连接迭代器中所有以换行符分隔的字符串。此数据在 writeData
函数中写入 cars.sql 文件。
$ cat cars.sql BEGIN TRANSACTION; CREATE TABLE cars(id INT, name TEXT, price INT); INSERT INTO "cars" VALUES(1,'Audi',52643); INSERT INTO "cars" VALUES(2,'Mercedes',57642); INSERT INTO "cars" VALUES(5,'Bentley',350000); INSERT INTO "cars" VALUES(6,'Hummer',41400); COMMIT;
转储的内存中 cars 表的内容。
现在我们将执行反向操作。我们将把转储的表导入回内存。
#!/usr/bin/env python2 # -*- coding: utf-8 -*- import sqlite3 as lite def readData(): f = open('cars.sql', 'r') with f: data = f.read() return data con = lite.connect(':memory:') with con: cur = con.cursor() sql = readData() cur.executescript(sql) cur.execute("SELECT * FROM cars") rows = cur.fetchall() for row in rows: print row
在这个脚本中,我们读取 cars.sql
文件的内容并执行它。这将重新创建转储的表。
def readData(): f = open('cars.sql', 'r') with f: data = f.read() return data
在 readData
方法内部,我们读取 cars.sql
表的内容。
cur.executescript(sql)
我们调用 executescript
方法来启动 SQL 脚本。
cur.execute("SELECT * FROM cars") rows = cur.fetchall() for row in rows: print row
我们验证数据。
$ ./import_table.py (1, u'Audi', 52643) (2, u'Mercedes', 57642) (5, u'Bentley', 350000) (6, u'Hummer', 41400)
输出显示我们已成功重新创建了保存的 cars 表。
Python SQLite 事务
事务是针对一个或多个数据库中的数据执行的数据库操作的原子单位。事务中所有 SQL 语句的效果要么全部提交到数据库,要么全部回滚。
在 SQLite 中,除了 SELECT
之外的任何命令都会启动一个隐式事务。此外,在一个事务中,像 CREATE TABLE
...、VACUUM
、PRAGMA
这样的命令会在执行前提交之前的更改。
手动事务以 BEGIN TRANSACTION
语句开始,并以 COMMIT
或 ROLLBACK
语句结束。
SQLite 支持三种非标准事务级别:DEFERRED
、IMMEDIATE
和 EXCLUSIVE
。SQLite Python 模块还支持自动提交模式,其中对表的所有更改都会立即生效。
#!/usr/bin/env python2 # -*- coding: utf-8 -*- import sqlite3 as lite import sys try: con = lite.connect('test.db') cur = con.cursor() cur.execute("DROP TABLE IF EXISTS friends") cur.execute("CREATE TABLE friends(id INTEGER PRIMARY KEY, name TEXT)") cur.execute("INSERT INTO friends(name) VALUES ('Tom')") cur.execute("INSERT INTO friends(name) VALUES ('Rebecca')") cur.execute("INSERT INTO friends(name) VALUES ('Jim')") cur.execute("INSERT INTO friends(name) VALUES ('Robert')") #con.commit() except lite.Error, e: if con: con.rollback() print e sys.exit(1) finally: if con: con.close()
我们创建一个 friends
表并尝试用数据填充它。但是,正如我们将看到的,数据并未提交。
#con.commit()
commit
方法被注释掉了。如果我们取消注释该行,数据将被写入表中。
sqlite> .tables cars friends images sqlite> SELECT Count(id) FROM friends; Count(id) ---------- 0 sqlite>
表已创建,但数据未写入表中。
在第二个示例中,我们演示了一些命令隐式地提交对数据库的先前更改。
#!/usr/bin/env python2 # -*- coding: utf-8 -*- import sqlite3 as lite import sys try: con = lite.connect('test.db') cur = con.cursor() cur.execute("DROP TABLE IF EXISTS friends") cur.execute("CREATE TABLE friends(id INTEGER PRIMARY KEY, name TEXT)") cur.execute("INSERT INTO friends(name) VALUES ('Tom')") cur.execute("INSERT INTO friends(name) VALUES ('Rebecca')") cur.execute("INSERT INTO friends(name) VALUES ('Jim')") cur.execute("INSERT INTO friends(name) VALUES ('Robert')") cur.execute("CREATE TABLE IF NOT EXISTS temporary(id INT)") except lite.Error, e: if con: con.rollback() print e sys.exit(1) finally: if con: con.close()
同样,我们没有显式调用 commit
命令。但这次,数据被写入 Friends 表中。
cur.execute("CREATE TABLE IF NOT EXISTS temporary(id INT)")
此 SQL 语句创建一个新表。它还提交了之前的更改。
$ ./implicit_commit.py sqlite> SELECT * FROM friends; id name ---------- ---------- 1 Tom 2 Rebecca 3 Jim 4 Robert
数据已写入 friends
表。
在自动提交模式下,SQL 语句会立即执行。
#!/usr/bin/env python2 # -*- coding: utf-8 -*- import sqlite3 as lite import sys try: con = lite.connect('test.db', isolation_level=None) cur = con.cursor() cur.execute("DROP TABLE IF EXISTS friends") cur.execute("CREATE TABLE friends(id INTEGER PRIMARY KEY, name TEXT)") cur.execute("INSERT INTO friends(name) VALUES ('Tom')") cur.execute("INSERT INTO friends(name) VALUES ('Rebecca')") cur.execute("INSERT INTO friends(name) VALUES ('Jim')") cur.execute("INSERT INTO friends(name) VALUES ('Robert')") except lite.Error, e: print e sys.exit(1) finally: if con: con.close()
在这个例子中,我们以自动提交模式连接到数据库。
con = lite.connect('test.db', isolation_level=None)
当我们设置 isolation_level
为 None 时,我们处于自动提交模式。
$ ./autocommit.py sqlite> SELECT * FROM friends; Id Name ---------- ---------- 1 Tom 2 Rebecca 3 Jim 4 Robert
数据已成功提交到 friends
表中。
这是 SQLite Python 教程。ZetCode 拥有一本完整的 SQLite Python 电子书
.