Python游标重置函数 python重新定义运算符( 五 )


到这里,我们展示了如何使用shelve模块打开(或创建)一个DBM文件,以及如何向其中添加项、编辑项、对其项进行迭代以及移除某个项 。
遗憾的是,在我们的数据设计中存在一个瑕疵 。发行者名称是重复的,这很容易导致不一致性,比如,发行者Danny DeVito可能被输入为"Danny De Vito",用于 一个电影;也可以输入为“Danny deVito",用于另一个 。为解决这一问题,可以使用两个DBM文件,主DVD文件使用标题键与(年份,时间长度,发行者ID)值; 发行者文件使用发行者ID (整数)键与发行者名称值 。下一节展示的SQL数据库 版程序将避免这一瑕疵 , 这是通过使用两个表格实现的,一个用于DVD,另一个用于发行者 。
12.2 SQL数据库
大多数流行的SQL数据库的接口在第三方模块中是可用的,Python带有sqlite3 模块(以及SQLite 3数据库),因此,在Python中 , 可以直接开始数据库程序设计 。SQLite是一个轻量级的SQL数据库,缺少很多诸如PostgreSQL这种数据库的功能, 但非常便于构造原型系统,并且在很多情况下也是够用的 。
为使后台数据库之间的切换尽可能容易 , PEP 249 (Python Database API Specification v2.0)提供了称为DB-API 2.0的API规范 。数据库接口应该遵循这一规范,比如sqlite3模块就遵循这一规范,但不是所有第三方模块都遵循 。API规范中指定了两种主要的对象 , 即连接对象与游标对象 。表12-1与表12-2中分别列出了这两种对象必须支持的API 。在sqlite3模块中,除DB-API 2.0规范必需的之外,其连接对象与游标对象都提供了很多附加的属性与方法 。
DVD程序的SQL版本为dvds.sql.py,该程序将发行者与DVD数据分开存储,以 避免重复,并提供一个新菜单 , 以供用户列出发行者 。该程序使用的两个表格在图12-1
def connect(filename):
create= not os.path.exists(filename)
db = sqlite3.connect(filename)
if create:
cursor = db.cursor()
cursor.execute("CREATE TABLE directors ("
"id INTEGER PRIMARY KEY AUTOINCREMENT UNIQUE NOT NULL, "
"name TEXT UNIQUE NOT NULL)")
cursor.execute("CREATE TABLE dvds ("
"id INTEGER PRIMARY KEY AUTOINCREMENT UNIQUE NOT NULL, "
"title TEXT NOT NULL, "
"year INTEGER NOT NULL,"
"duration INTEGER NOT NULL, "
"director_id INTEGER NOT NULL, ”
"FOREIGN KEY (director_id) REFERENCES directors)")
db.commit()
return db
sqlite3.connect()函数会返回一个数据库对象,并打开其指定的数据库文件 。如果该文件不存在,就创建一个空的数据库文件 。鉴于此 , 在调用sqlite3.connect()之前,我们要注意数据库是否是准备从头开始创建,如果是,就必须创建该程序要使用的表格 。所有査询都是通过一个数据库游标完成的,可以从数据库对象的cursor()方法获取 。
注意,两个表格都是使用一个ID字段创建的 , ID字段有一个AUTOINCREMENT 约束——这意味着SQLite会自动为ID字段赋予唯一性的数值,因此,在插入新记录时,我们可以将这些字段留给SQLite处理 。
SQLite支持有限的数据类型——实际上就是布尔型、数值型与字符串——但使用数据'‘适配器”可以对其进行扩展,或者是扩展到预定义的数据类型(比如那些用于日期与datetimes的类型),或者是用于表示任意数据类型的自定义类型 。DVD程序并不需要这一功能,如果需要 , sqlite3模块的文档提供了很多详细解释 。我们使用的外部键语法可能与用于其他数据库的语法不同 , 并且在任何情况下,只是记录我们的意图,因为SQLite不像很多其他数据库那样需要强制关系完整性,sqlite3另一点与众不同的地方在于其默认行为是支持隐式的事务处理,因此,没有提供显式的“开始事务” 方法 。

推荐阅读