Python SQLite教程
如果您正在寻找可以在应用程序中使用完整的数据库操作而无需安装任何数据库服务器程序(例如MySQL,PostgreSQL或者Oracle)的工具,则可以使用pythonsqlite3
模块。
Python SQLite
Python sqlite3是一个出色的模块,您可以通过它使用应用程序中的内存和持久数据库执行所有可能的数据库操作。
此模块将Python DB API接口实现为兼容的解决方案,用于在程序中实现与SQL相关的操作。
使用sqlite3模块
在本节中,我们将开始在应用程序中使用sqlite3模块,以便我们可以其中创建数据库和表并对其执行各种DB操作。
让我们开始吧。
Python SQLite创建数据库
在谈论数据库时,我们正在查看一个文件,该文件将存储在文件系统中,并且其访问权限由模块本身管理,以防止多个用户尝试写入文件时损坏文件。
这是一个示例程序,可在打开新数据库进行操作之前创建一个新数据库:
import os import sqlite3 db_filename = 'theitroad.db' db_exists = not os.path.exists(db_filename) connection = sqlite3.connect(db_filename) if db_exists: print('No schema exists.') else: print('DB exists.') connection.close()
我们将运行该程序两次,以检查其是否正常运行。
Python SQLite创建表
要开始使用数据库,我们必须定义一个表架构,在该架构上我们将编写进一步的查询并执行操作。
这是我们将遵循的架构:
Python SQLite表架构
对于相同的架构,我们接下来将编写相关的SQL查询,并将这些查询保存在book_schema.sql
中:
CREATE TABLE book ( name text primary key, topic text, published date ); CREATE TABLE chapter ( id number primary key autoincrement not null, name text, day_effort integer, book text not null references book(name) );
现在让我们使用connect()
函数连接到数据库,并使用executescript()
函数插入一些初始数据:
import os import sqlite3 db_filename = 'theitroad.db' schema_filename = 'book_schema.sql' db_exists = not os.path.exists(db_filename) with sqlite3.connect(db_filename) as conn: if db_exists: print('Creating schema') with open(schema_filename, 'rt') as file: schema = file.read() conn.executescript(schema) print('Inserting initial data') conn.executescript(""" insert into book (name, topic, published) values ('theitroad', 'Java', '2011-01-01'); insert into chapter (name, day_effort, book) values ('Java XML', 2,'theitroad'); insert into chapter (name, day_effort, book) values ('Java Generics', 1, 'theitroad'); insert into chapter (name, day_effort, book) values ('Java Reflection', 3, 'theitroad'); """) else: print('DB already exists.')
当我们执行程序并检查章节表中所有数据时,我们将看到以下输出:
具有初始数据的数据库
看看我是如何从命令行请求db文件目录的。在下一节中,我们将从sqlite3模块本身查询数据。
Python SQLite游标选择
现在,我们将通过使用游标读取满足某些条件的所有章节来检索脚本中的数据:
import sqlite3 db_filename = 'theitroad.db' with sqlite3.connect(db_filename) as conn: cursor = conn.cursor() cursor.execute(""" select id, name, day_effort, book from chapter where book = 'theitroad' """) for row in cursor.fetchall(): id, name, day_effort, book = row print('{:2d} ({}) {:2d} ({})'.format( id, name, day_effort, book))
让我们看看该程序的输出:从数据库中获取数据
这是一个简单的示例,该数据是从一列与特定值匹配的表中获取数据的。
获取表的元数据
在我们的程序中,获取表的元数据用于文档编制以及其他目的也很重要:
import sqlite3 db_filename = 'theitroad.db' with sqlite3.connect(db_filename) as connection: cursor = connection.cursor() cursor.execute(""" select * from chapter where book = 'theitroad' """) print('Chapter table has these columns:') for column_info in cursor.description: print(column_info)
由于创建schema时的原因,我们没有提供列名称以外的任何内容,大多数值都是None。
使用命名参数
使用命名参数,我们可以将参数传递给脚本,因此可以传递给我们在程序中编写的SQL查询。
使用命名参数非常简单,让我们看一下如何做到这一点:
import sqlite3 import sys db_filename = 'theitroad.db' book_name = sys.argv[1] with sqlite3.connect(db_filename) as conn: cursor = conn.cursor() query = """ select id, name, day_effort, book from chapter where book = :book_name """ cursor.execute(query, {'book_name': book_name}) for row in cursor.fetchall(): id, name, day_effort, book = row print('{:2d} ({}) {:2d} ({})'.format( id, name, day_effort, book))
我们来看一下该程序的输出:传递命名参数
看看在执行之前传递一个命名参数并在查询中替换它是多么容易。
Python SQLite3事务管理
好吧,事务是关系数据库众所周知的功能。
sqlite3模块完全能够管理事务的内部状态,我们唯一需要做的就是让它知道事务即将发生。
这是一个示例程序,描述了我们如何通过显式调用commit()
函数在程序中编写事务:
import sqlite3 db_filename = 'theitroad.db' def show_books(conn): cursor = conn.cursor() cursor.execute('select name, topic from book') for name, topic in cursor.fetchall(): print(' ', name) with sqlite3.connect(db_filename) as conn1: print('Before changes:') show_books(conn1) # Insert in one cursor cursor1 = conn1.cursor() cursor1.execute(""" insert into book (name, topic, published) values ('Welcome Python', 'Python', '2013-01-01') """) print('\nAfter changes in conn1:') show_books(conn1) # Select from another connection, without committing first print('\nBefore commit:') with sqlite3.connect(db_filename) as conn2: show_books(conn2) # Commit then select from another connection conn1.commit() print('\nAfter commit:') with sqlite3.connect(db_filename) as conn3: show_books(conn3)
在提交conn1之前调用show_books(...)函数时,结果取决于所使用的连接。
由于是从conn1
中进行的更改,因此可以看到所做的更改,但conn2
没有。
提交所有更改后,所有连接都可以看到所做的更改,包括" conn3"。