目录
SQLite数据库
SQLite数据类型
Python数据类型与SQLite数据类型的映射
使用GUI管理工具管理SQLite数据库
数据库编程的基本操作过程
sqlite3模块API
数据库连接对象Connection
游标对象Cursor
数据库的CRUD操作示例
示例中的数据表
无条件查询
有条件查询
插入数据
更新数据
删除数据
防止SQL注入攻击
如果数据量较少,则我们可以将数据保存到文件中;如果数据量较大,则我们可以将数据保存到数据库中。
SQLite数据库
SQLite是嵌入式系统使用的关系数据库,目前的主流版本是SQLite3。SQLite是开源的,采用C语言编写而成,具有可移植性强、可靠性高 、小而易用等特点。SQLite提供了对SQL-92标准的支持,支持多表、索引、事务、视图和触发。
SQLite数据类型
SQLite是无数据类型的数据库,在创建表时不需要为字段指定数据类型。但从编程规范上讲,我们应该指定数据类型,因为数据类型可以表明这个字段的含义,便于我们阅读和理解代码。 SQLite支持的常见数据类型如下。
INTEGER:有符号的整数类型。
REAL:浮点类型。
TEXT:字符串类型,采用UTF-8和UTF-16字符编码。
BLOB:二进制大对象类型,能够存放任意二进制数据。
注意:SQLite是为嵌入式设备(如智能手机等)设计的数据库。SQLite在运行时与使用它的应用程序之间共用相同的进程空间。而在运行时,Oracle和MySQL程序与使用它的应用程序在两个不同的进程中。
Python数据类型与SQLite数据类型的映射
在使用Python访问SQLite数据库时,会经常涉及数据类型的互相转换。它们的映射关系如下表所示。
使用GUI管理工具管理SQLite数据库
SQLite数据库本身自带一个基于命令提示符的管理工具,使用起来很困难。如果使用GUI管理工具,则需要使用第三方工具。第三方GUI管理工具有很多,例如Sqliteadmin Administrator、DB Browser for SQLite、SQLiteStudio等。DB Browser for SQLite对中文支持很好,所以推荐使用该工具。
(1)安装和启动DB Browser for SQLite
在官网下载DB.Browser.for.SQLite-3.11.2-win32.zip安装包文件,将该文件解压到一个目录中,在解压目录下找到DB Browser for SQLite.exe文件,双击该文件即可启动DB Browser for SQLite工具。
(2)创建数据库
一个SQLite数据库对应一个SQLite数据文件,为了测试DB Browser for SQLite工具,我们要先创建SQLite数据库。
在上图所示的界面单击工具栏中的“新建数据库”按钮,弹出保存文件对话框。
(3)创建数据表
在一个SQLite数据库中可以包含多个数据表。在上图所示的界面单击“保存”按钮,弹出建表对话框。
注意:候选键与主键类似,都不可以重复,但候选键可以为空,而主键不能为空。
(4)执行SQL语句
使用DB Browser for SQLite工具,可以执行任意合法的SQL语句。
(5)浏览数据
DB Browser for SQLite常用于浏览数据。
数据库编程的基本操作过程
数据库编程主要分为两类:查询(Read)和修改(C插入、U更新 、D删除)。
(1)查询数据
查询数据时需要6步,在查询过程中需要提取数据结果集,最后释放资源,即关闭游标和数据库。
(2)修改数据
修改数据时如上图所示,最多需要6步,在修改过程中如果执行SQL操作成功,则提交数据库事务;如果失败,则回滚事务。最后释放资源,关闭游标和数据库。
数据库事务是修改数据库的一系列操作,这些操作要么全部执行,要么全部不执行。若全部操作执行成功,则确定修改,称之为“提交事务”;如果有操作执行失败,则放弃修改,称之为“回滚事务”
sqlite3模块API
Python官方提供了sqlite3模块来访问SQLite数据库。
数据库连接对象Connection
数据库访问的第一步是进行数据库连接。
我们可以通过connect(database)函数建立数据库连接,参数database是SQLite数据库的文件路径,如果连接成功,则返回数据库连接对象Connection。
Connection对象有如下重要的方法。
close():关闭数据库连接,在关闭之后再使用数据库连接将引发异常。
commit():提交数据库事务。
rollback():回滚数据库事务。
cursor():获得Cursor游标对象。
游标对象Cursor
一个Cursor游标对象表示一个数据库游标,游标暂时保存了SQL操作所影响到的数据。游标是通过数据库连接创建的。
游标Cursor对象有很多方法和属性,其中的基本SQL操作方法如下 。
execute(sql[,parameters]):执行一条SQL语句,sql是SQL语句 ,parameters是为SQL提供的参数,可以是序列或字典类型。返回值是整数,表示执行SQL语句影响的行数。
executemany(sql[,seq_of_params]):执行批量SQL语句,sql是SQL语句,seq_of_params是为SQL提供的参数,seq_of_params是序列。 返回值是整数,表示执行SQL语句影响的行数。
在通过execute()和executemany()方法执行SQL查询语句后, 还要通过提取方法从查询结果集中返回数据,相关提取方法如下。
fetchone():从结果集中返回只有一条记录的序列,如果没有数据,则返回None。
fetchmany(size=cursor.arraysize):从结果集中返回小于等于size记录数的序列,如果没有数据,则返回空序列,size在默认情况下是整个游标的行数。
fetchall():从结果集中返回所有数据。
数据库的CRUD操作示例
对数据库表中的数据可以进行4类操作:数据插入(Create)、数据查询(Read)、数据更新(Update)和数据删除(Delete),即增、删 、改、查。
示例中的数据表
为了介绍数据库的CRUD操作,这里修改前面school_db数据库中的student(学生)表。
为了查询方便,我们预先插入几条记录。
无条件查询
SQL查询语句是SELECT,根据是否带有WHERE子句,分为:无条件查询和有条件查询,本节先介绍无条件查询。 无条件查询最为简单,没有WHERE子句。
示例代码如下:
import sqlite3
try:# 1.建立数据库连接con=sqlite3.connect('school_db.db')# 2.创建游标对象cursor=con.cursor()# 3.执行SQL查询操作sql='SELECT s_id,s_name,s_sex,s_birthday FROM student'cursor.execute(sql)# 提取结果集result_set=cursor.fetchall() # 从结果集中返回所有数据for row in result_set: # 遍历结果集print('学号:{0}-姓名:{1}-性别:{2}-生日:{3}'.format(row[0],row[1],row[2],row[3]))
except sqlite3.Error as e:print('数据查询发生错误:{}'.format(e))
finally:# 5.关闭游标if cursor:cursor.close()# 6.关闭数据连接if con:con.close()
通过Python指令运行文件。
有条件查询
有条件查询带有WHERE子句,WHERE子句是查询条件。
示例代码如下:
import sqlite3
istr=input('请输入生日(yyyyMMdd):') # 从控制台输入查询条件(生日)
try:# 1.建立数据库连接con=sqlite3.connect('school_db.db')# 2.创建游标对象cursor=con.cursor()# 3.执行SQL查询操作sql='SELECT s_id,s_name,s_sex,s_birthday FROM student FROM student WHERE s_birthday < ?' # 查询条件中的占位符cursor.execute(sql,[istr]) # 参数放到序列或元组中# 4.提取结果集result_set=cursor.fetchall() # 从结果集中返回所有数据for row in result_set: # 遍历结果集print('学号:{0}-姓名:{1}-性别:{2}-生日:{3}'.format(row[0],row[1],row[2],row[3]))
except sqlite3.Error as e:print('数据查询发生错误:{}'.format(e))
finally:# 5.关闭游标if cursor:cursor.close()# 6.关闭数据连接if con:con.close()
通过Python指令运行文件。
插入数据
数据插入操作SQL语句是INSERT。
示例代码如下:
import sqlite3
i_name=input('请输入【姓名】:')
i_sex=input('请输入【性别】:')
i_birthday=input('请输入【生日】(yyyyMMdd):')try:# 1.建立数据库连接con=sqlite3.connect('school_db.db')# 2.创建游标对象cursor=con.cursor()# 3.执行SQL查询操作sql='INSERT INTO student (s_name,s_sex,s_birthday) VALUES(?,?,?)' # 查询条件中的占位符cursor.execute(sql,[i_name,i_sex,i_birthday]) # 参数放到序列或元组中# 4.提交数据库事务con.commit() # 插入成功,提交事务print('插入数据成功。')
except sqlite3.Error as e:print('数据查询发生错误:{}'.format(e))# 4.回滚数据库事务con.rollback() # 插入失败,回滚事务
finally:# 5.关闭游标if cursor:cursor.close()# 6.关闭数据连接if con:con.close()
通过Python指令运行文件。
数据插入成功,可以使用DB Browser for SQLite浏览数据。
更新数据
数据更新操作SQL语句是UPDATE。
示例代码如下:
import sqlite3
i_id=input('请输入【学号】:')
i_name=input('请输入【姓名】:')
i_sex=input('请输入【性别】:')
i_birthday=input('请输入【生日】(yyyyMMdd):')try:# 1.建立数据库连接con=sqlite3.connect('school_db.db')# 2.创建游标对象cursor=con.cursor()# 3.执行SQL查询操作sql='UPDATE student SET s_name=?,s_sex=?,s_birthday=? WHERE s_id=?' # 查询条件中的占位符cursor.execute(sql,[i_name,i_sex,i_birthday,i_id]) # 参数放到序列或元组中# 4.提交数据库事务con.commit() # 插入成功,提交事务print('插入数据成功。')
except sqlite3.Error as e:print('数据查询发生错误:{}'.format(e))# 4.回滚数据库事务con.rollback() # 插入失败,回滚事务
finally:# 5.关闭游标if cursor:cursor.close()# 6.关闭数据连接if con:con.close()
通过Python指令运行文件。
数据更新成功,可以使用DB Browser for SQLite浏览数据。
删除数据
数据删除操作SQL语句是DELETE。
示例代码如下:
import sqlite3
i_id=input('请输入要删除学生的【学号】:')try:# 1.建立数据库连接con=sqlite3.connect('school_db.db')# 2.创建游标对象cursor=con.cursor()# 3.执行SQL查询操作sql='DELETE FROM student WHERE s_id=?' # 查询条件中的占位符cursor.execute(sql,[i_id]) # 参数放到序列或元组中# 4.提交数据库事务con.commit() # 插入成功,提交事务print('插入数据成功。')
except sqlite3.Error as e:print('数据查询发生错误:{}'.format(e))# 4.回滚数据库事务con.rollback() # 插入失败,回滚事务
finally:# 5.关闭游标if cursor:cursor.close()# 6.关闭数据连接if con:con.close()
通过Python指令运行文件。
数据更新成功,可以使用DB Browser for SQLite浏览数据。
防止SQL注入攻击
# 3.执行SQL查询操作sql='SELECT s_id,s_name,s_sex,s_birthday FROM student WHERE s_birthday <'+istr # 查询条件中的占位符cursor.execute(sql)
在构建SQL语句时,参数采用占位符占位,在执行时再传递实参,这种方式太麻烦!不仅是查询操作,所有的SQL语句构建都可以采用拼接参数实现,但有一个潜在风险——会受到“SQL注入攻击”。SQL注入攻击指在传递实参时,使用特殊字符或SQL关键字,在拼接成SQL后,这条SQL语句就有一定的攻击性!