数据库
数据库(Database)是计算机系统中用于存储、管理和访问数据的核心组件,也被称为数据存储库(Data Store)。以下是对数据库的详细解释:
一、定义与基本概念
- 定义:数据库是指存储数据的容器,它能够存储大量结构化和非结构化的数据,包括文本、数字、图像、音频等各种类型的数据。
- 基本概念:数据库由若干个相关数据的集合组成,这些数据被组织在表格、集合或其他数据结构中,以便于进行高效的管理、处理和访问。
二、数据库的类型
- 关系型数据库:使用表格(二维结构)来组织和存储数据,通过结构化查询语言(SQL)进行数据管理和查询。常见的关系型数据库包括MySQL、Oracle Database、Microsoft SQL Server、PostgreSQL等。
- 非关系型数据库(NoSQL) :不使用传统的关系型数据库模型,而是采用其他数据模型(如键值对、文档、图形、列族等)来组织和管理数据。常见的非关系型数据库有MongoDB、Cassandra、Redis、Elasticsearch等。
- 文档数据库:如MongoDB,存储数据为文档形式,每个文档都是一个JSON或类似JSON的对象。
- 键值数据库:如Redis,使用简单的键值对来存储数据。
- 列族数据库:如Apache Cassandra,将数据存储在列族中,每个列族包含多个列,列可以动态地增减。
- 图形数据库:如Neo4j,基于图的数据模型,使用节点和边来表示实体和关系,适用于社交网络分析等领域。
三、数据库的结构与设计
- 数据建模:数据库设计的核心部分,将业务需求转化为数据库的数据结构和关系,一般采用E-R图(实体-关系图)来表示。
- 数据库设计:将数据模型转化为数据库的实际结构,包括数据库表格的设计、字段的定义、数据类型的选择、主键和外键的定义等。
- 数据库实现:将数据库设计转化为实际的数据库系统,包括数据库软件的安装、数据库表格的创建、数据的导入和检验等。
四、数据库管理
- 广义定义:包括数据库设计以后的一切数据库管理活动,如数据库模型创建、数据加载、数据库系统日常维护活动等。
- 狭义定义:特指数据库系统运行期间采取的活动,如数据服务、性能监督、数据库重组、数据库重构、数据库完整性控制和安全性控制、数据库恢复等。
- 数据库管理员(DBA):负责数据库的日常管理和维护工作,确保数据库的稳定性和安全性。
五、数据库的应用
数据库在现代社会中有着极其广泛的应用,几乎涵盖了所有需要数据存储、管理和分析的行业和领域。例如:
- 企业应用:用于存储、管理和访问业务数据,如客户信息、销售数据和生产数据等。
- 金融行业:用于存储、管理和分析金融数据,如账户余额、交易历史和股票价格等。
- 医疗行业:用于存储、管理和分析患者病历、医疗图像和药物信息等。
- 教育行业:用于存储、管理和分析学生信息、课程内容和教育资源等。
- 互联网应用:如社交媒体、电子商务等,需要存储大量的用户信息、网站内容和交易数据。
六、数据库的优势
- 数据共享:数据库系统允许多用户、多应用共享数据,减少了数据的冗余度,节约了存储空间。
- 数据独立性:数据库系统提供了数据的物理独立性和逻辑独立性,使得应用程序与数据库中的数据相互独立。
- 数据安全性和完整性:数据库系统通过统一的数据管理和控制,保证了数据的安全性和完整性。
- 高效的数据处理:数据库系统提供了高效的数据查询、更新和删除等操作,支持复杂的数据分析和处理。
数据必须以某种方式存储起来才有价值,数据库实际上是一组相关数据的集合。数据库编程的相关技术有很多,涉及具体的数据库安装、配置和管理,还要掌握SQL语句,最后才能编写程序访问数据库。
数据持久化技术概述
凡是将数据保存到存储介质中,需要时能再找出来,并能够对数据进行修改,就属于数据持久化。例如:把数据保存到数据库中。而在Python中关于数据持久化的技术有很多,其中比较常用的有:
文本文件:通过Python文件操作和管理技术将数据保存到文本文件中,然后进行读写操作,这些文件一般是结构化的文档,如XML文档和JSON等文件。结构化文档是指在文件内部采取某种方式将数据组织起来的文件。
数据库:将数据保存在数据库中之后可以通过数据库管理系统(DBMS)来对数据进行管理,该系统支持事务处理、并发访问、高级查询和SQL。Python中将数据保存到数据库中的技术有很多,但主要分为两类:遵循 Python DB-API 规范技术 和 ORM(Object-Relational Mapping 对象关系映射) 技术(它能将对象保存到数据库表中)。Python DB-API 规范通过在Python中编写SQL语句访问数据库。
Python DB-API 规范一定会依托某个数据库管理系统。可以点击我的主页查看我之前发过的 MySQL数据库教程一文。
Python DB-API
在有Python DB-API 规范之前,各个数据库编程接口非常混乱,实现方式差别很大,更换数据库工作量非常大。Python DB-API 规范要求各个数据库厂商和第三方开发商,遵循统一的编程接口,这使得Python开发数据库变得统一而简单,更新数据库工作量很小。
Python DB-API 只是一个规范,没有访问数据库的具体实现,规范是用来约束数据库厂商的,要求数据库厂商为开发人员提供访问数据库的标准接口。
- Python官方制定了Python DB-API 规范,这个规范包括全局变量、连接、游标、数据类型和异常等内容。
- 数据库厂商为了支持Python语言访问自己的数据库,根据这些Python DB-API 规范提供了具体的实现类,如连接和游标对象具体实现方式。当然针对某种数据库也可能有其他第三方实现。
- 对于开发人员而言,Python DB-API 规范提供了一致的API接口,开发人员不用关心实现接口的细节。
建立数据库连接
数据库访问的第一步是进行数据库连接。建立数据库连接可以通过connect(parameters...)函数实现,该函数根据parameters参数连接数据库,连接成功返回Connection对象。连接数据库代码如下:
import pymysql #导入模块
connectio = pymysql.connect(host='数据库主机名或IP地址',
user='访问数据库账号',
password='访问数据库密码',
databse='数据库中的库名',
port='连接数据库的端口号',
charset='数据库编码格式')
其中password也可以改为passwd,database也可以改为db,charset参数中输入"utf8"是配置数据库串集 UTF-8 编码。
注意:连接参数虽然主要包括数据库主机名或IP地址、用户名、密码等内容,但是不同数据库厂商(或第三方开发商)提供的开发模块会有所不同,具体使用时需要查询开发文档。此外,在使用前需要先下载 PyMySQL库,通过命令"pip install PyMySQL"即可。
|------------|-----------------------------|
| 方法名 | 说明 |
| close() | 关闭数据库连接,若数据库已经关闭连接再使用则会引发异常 |
| commit() | 提交数据库事务 |
| rollback() | 回滚数据库事务 |
| cursor() | 获得 Cursor 游标对象 |
[Connection对象的部分重要方法]
注意:数据库事务通常包含了多个对数据库的读/写操作,这些操作是有序的。若事务被提交给了数据库管理系统,则数据库管理系统需要确保该事务中的所有操作都完成成功,结果被永久保存在数据库中。如果事务中有的操作没有完成,则事务中的所有操作都需要被回滚,回到事务执行前的状态。同时,该事务对数据库或者其他事务的执行无影响,所有的事务都看似在独立地运行。
创建游标
一个Cursor游标对象表示一个数据库游标,游标暂时保存了SQL操作所影响到的数据。在数据库事务管理中游标非常重要,游标是通知数据库连接创建的,相同数据库连接创建的游标所引起的数据变化,会马上反映到同一连接中的其他游标对象。但是不同数据库连接中的游标,是否能及时反映出来,则与数据库事务管理有关。
游标Cursor对象有很多属性和方法,其中基本SQL操作方法如下:
(1)execute(operation[,parameters])
执行一条SQL语句,operation是SQL语句,parameters是为SQL提供的参数,可以是序列或字典类型。返回值是整数,表示执行SQL语句影响的行数。
(2)executemany(operation[,seq_of_params])
批量执行SQL语句,operation是SQL语句,seq_of_params是为SQL提供的参数,seq_of_params是序列。返回值是整数,表示执行SQL语句影响的行数。
(3)callproc(procname[,parameters])
执行存储过程,procname是存储过程名,parameters是为存储过程提供的参数。
执行SQL查询语句也是通过 execute() 和 executemany() 方法实现的,但是这两个方法返回的都是整数,对于查询没有意义。因此使用 execute() 和 executemany() 方法实现后,还要通过提取方法提取结果集
方法名 | 说明 |
---|---|
fetchone() | 从结果集中返回一条记录的序列,如果没有数据则返回None |
fetchmany([size=cursor.arraysize]) | 从结果集返回小于或等于size的记录数序列,如果没有数据返回空序列,size默认情况下是整个游标的行数 |
fetchall() | 从结果集返回所有数据 |
[相关提取方法] |
示例:对User表进行CRUD操作
对数据库表中的数据可以进行四类操作:数据插入(Create)、数据删除(Delete)、数据更新(Update)和数据查询(Read),也就是"增删改查"。
PyMySQL遵从Python DA-API2 规范,其中包含了纯Python实现的MySQL客户端。PyMySQL兼容MySQLdb,MySQLdb是Python2中使用的数据库开发模块。
安装PyMySQL库
打开命令提示符,输入下面代码
pip install PyMySQL
pip 是Python 官方提供的包管理工具,Python默认安装就会安装 pip 工具。(pip 服务器在国外,有的库下载安装很慢,甚至有的库无法安装。此时可以使用国内的镜像服务器,需要在 pip 指令后面加 -i 参数后面跟镜像服务器网址)
修改指令如下(此处镜像服务器由清华大学提供,也可以使用其他镜像服务器)
pip install PyMySQL -i https://pypi.tuna.tsinghua.edu.cn/simple
数据库编程一般过程(如下图)
其中查询(Read)和修改(C插入、U更新、D删除)过程都是最多需要6个步骤。查询过程中需要提取数据结果集,这是修改过程中没有的步骤。而修改过程中如果成功执行SQL操作则提交数据库事务,如果失败则回滚事务。最后需要释放资源,即关闭游标和数据库。
为了执行CRUD操作,首先需要使用数据库创建表,此处我使用的是MySQL数据库,如果有不知道的可以参考下文:
MySQL数据库教程-CSDN博客https://blog.csdn.net/2302_76708905/article/details/140368123首先打开MySQL客户端,然后输入密码进入后再输入下面命令(用于创建数据库MyDB)
CREATE DATABASE IF NOT EXISTS MyDB;
按回车键执行后看到下图则为成功
接下来输入下面命令选择数据库
use MyDB;
按回车键执行后看到下图则为成功
接下来输入下面命令创建用户表,此处用户表假设为两个字段(用户id、用户密码)
CREATE TABLE IF NOT EXISTS user(
name varchar(20),
userid int,
PRIMARY KEY(userid));
按回车键执行后看到下图则为成功
接下来输入下面命令插入原始数据
INSERT INTO user VALUES("Tom",1);
INSERT INTO user VALUES("Ben",2);
INSERT INTO user VALUES("张三",3);
按回车键执行后看到下图则为成功
数据库查询操作
接下来查询上面建立的MyDB数据库
(1)有条件查询
输入下面示例代码
import pymysql
# 1.建立数据库连接
connection = pymysql.connect(host='localhost',#代表本地主机
user='用户名',
password='密码',
database='MyDB',
charset='utf8')# MySQL数据库默认安装以及默认创建的数据库都是UTF-8编码
try:
# 2.创建游标对象
with connection.cursor() as cursor:
# 3.执行SQL操作
sql = 'select name,userid from user where userid>%(id)s'# %(id)s是命名占位符
cursor.execute(sql,{'id':0})# 执行sql语句并绑定参数
# 4.提取结果集
result_set = cursor.fetchall()
for row in result_set:
print('id:{0}-name:{1}'.format(row[1],row[0]))
# 5.关闭游标
finally:
# 6.关闭数据库连接
connection.close()
代码运行结果如下
可能看到代码时大家会有疑问:为什么数据库连接不使用类似于游标的with代码块管理资源呢?因为数据库连接如果出现异常,程序再往后执行数据库操作已经没有任何意义了,因此数据库连接不需要放到try-except语句中,也不需要with代码块管理。
注意:提交字段时,字段的顺序是select语句中列出的字段顺序,不是数据表中字段的顺序,除非使用select*语句。
(2)无条件查询
输入下面示例代码
import pymysql
# 1.建立数据库连接
connection = pymysql.connect(host='localhost',
user='root',
password='123456',
database='MyDB',
charset='utf8')
try:
# 2.创建游标对象
with connection.cursor() as cursor:
# 3.执行SQL操作
sql = 'select max(userid) from user'# 使用max等函数
cursor.execute(sql)
# 4.提取结果集
row = cursor.fetchone()
if row is not None:
print("最大用户id:{0}".format(row[0]))
# 5.关闭游标
finally:
# 6.关闭数据库连接
connection.close()
代码执行结果如下
最大用户id:3
Process finished with exit code 0
数据库修改操作
1.数据插入
输入下面示例代码
import pymysql
# 查询最大用户id
def read_max_userid():
# 1.建立数据库连接
connection = pymysql.connect(host='localhost',
user='root',
password='123456',
database='MyDB',
charset='utf8')
try:
# 2.创建游标对象
with connection.cursor() as cursor:
# 3.执行SQL操作
sql = 'select max(userid) from user' # 使用max等函数
cursor.execute(sql)
# 4.提取结果集
row = cursor.fetchone()
return row[0]
# 5.关闭游标
finally:
# 6.关闭数据库连接
connection.close()
# 1.建立数据库连接
connection = pymysql.connect(host='localhost',
user='root',
password='123456',
database='MyDB',
charset='utf8')
# 查询最大值
maxid = read_max_userid()
try:
# 2.创建游标对象
with connection.cursor() as cursor:
# 3.执行SQL操作
sql = 'insert into user(userid,name) values(%s,%s)'
nextid = maxid+1
name = 'Tony'+str(nextid)
cursor.execute(sql,(nextid,name))
print('影响的行数:{0}'.format(cursor.rowcount))
# 4.提交数据库事务
connection.commit()
# 5.关闭游标
except pymysql.DatabaseError:
# 4.回滚数据库事务
connection.rollback()
finally:
# 6.关闭数据库连接
connection.close()
代码执行结果
影响的行数:1
Process finished with exit code 0
此时可以看到上面这段代码不够完美,有许多重复的代码,可以进一步进行优化,代码优化的目标是提高可读性、可维护性,并确保资源的正确管理。优化可以使用上下文管理器(with语句) 来确保数据库连接在使用后能够正确关闭。封装数据库操作 到函数中,避免代码重复。异常处理确保在出现错误时能够回滚事务并关闭数据库连接等。
2.数据更新
示例代码如下
import pymysql
# 1.建立数据库连接
connection = pymysql.connect(host='localhost',
user='root',
password='123456',
database='MyDB',
charset='utf8')
try:
# 2.创建游标对象
with connection.cursor() as cursor:
# 3.执行SQL操作
sql = 'update user set name= %s where userid > %s'
affectedcount = cursor.execute(sql,('Tom',3))
print('影响的行数:{0}'.format(affectedcount))
# 4.提交数据库事务
connection.commit()
# 5.关闭游标
except pymysql.DatabaseError as e:
# 4.回滚数据库事务
connection.rollback()
print(e)
finally:
# 6.关闭数据库连接
connection.close()
代码运行结果
影响的行数:1
Process finished with exit code 0
3.数据删除
示例代码如下
import pymysql
# 查询最大用户id
def read_max_userid():
# 1.建立数据库连接
connection = pymysql.connect(host='localhost',
user='root',
password='123456',
database='MyDB',
charset='utf8')
try:
# 2.创建游标对象
with connection.cursor() as cursor:
# 3.执行SQL操作
sql = 'select max(userid) from user' # 使用max等函数
cursor.execute(sql)
# 4.提取结果集
row = cursor.fetchone()
return row[0]
# 5.关闭游标
finally:
# 6.关闭数据库连接
connection.close()
# 1.建立数据库连接
connection = pymysql.connect(host='localhost',
user='root',
password='123456',
database='MyDB',
charset='utf8')
# 查询最大值
maxid = read_max_userid()
try:
# 2.创建游标对象
with connection.cursor() as cursor:
# 3.执行SQL操作
sql = 'delete from user where userid = %s'
affectcount = cursor.execute(sql, (maxid))
print('影响的行数:{0}'.format(affectcount))
# 4.提交数据库事务
connection.commit()
# 5.关闭游标
except pymysql.DatabaseError:
# 4.回滚数据库事务
connection.rollback()
finally:
# 6.关闭数据库连接
connection.close()
代码运行结果
影响的行数:1
Process finished with exit code 0
从上述案例中不难看出:数据更新、数据删除和数据插入在程序结构上非常相似,差别主要在于SQL语句和绑定的参数不同。
NoSQL数据库存储
目前大部分数据库都是关系型的,通过SQL语句操作数据库。但也有一些数据库是非关系型的,不通过SQL语句操作数据库,这些数据库称为NoSQL是数据库。dbm(data base manager)数据库是最简单的NoSQL数据库,它不需要安装,直接通过键值对数据存储。
dbm数据库的打开和关闭
与关系型数据库类似,dbm数据库使用前需要打开,使用完成需要关闭。打开数据库使用open()函数,它的语法如下:
dbm.open(file,flag='r')
参数file是数据库文件名,包含路径;参数flag是文件打开方式,flag取值说明如下:
r:以只读方式打开现有数据库,这是默认值
w:以读写方式打开现有数据库
c:以读写方式打开现有数据库,如果数据库不存在则创建
n:始终创建一个新的空数据库,打开方式为读写
关闭数据库使用close()函数,该函数没有参数;此外也可以使用with语句,此时则不需要使用close语句来释放资源。示例代码如下
with dbm.open(filename,'r') as db:
pass
dbm数据存储
dbm数据存储方式类似于字典数据结构,通过键写入或读取数据。但需要注意dbm数据库保存的数据是字符串类型或字节(bytes)类型。
dbm数据存储相关语句如下:
(1)写入数据
d[key] = data
d是打开的数据库对象,key是键,data是要保存的数据。如果key不存在则创建key-data数据项,如果key已经存在则使用data覆盖旧数据。
(2)读取数据
data = d[key] 或 data = d.get(key,defaultvalue)
使用 data = d[key] 读取数据时,如果没有key对应的数据则会抛出KeyError异常。为了防止这种情况的发生,可以使用 data = d.get(key,defaultvalue) 语句,如果没有key对应的数据,则会放回默认值defaultvalue。
(3)删除数据
del d[key]
按照key删除数据,如果没有key对应的数据则会抛出KeyError异常。
(4)查找数据
flag = key in d
按照key在数据库中查找数据,示例代码如下
import dbm
with dbm.open('mydb_name','c') as db:
db['name'] = 'tony' # 更新数据
print(db['name'].decode()) # 取出数据
age = int(db.get('age',b'18').decode()) # 取出数据
print(age)
if 'age' in db: # 判断是否存在age数据
db['age'] = '20' # 或者b'20'
del db['name'] #删除name数据
db['name']表达式取出的数据是字节序列,如果需要的是字符串则需要使用decode()方法将字节序列转换为字符串。
参考书籍:《python从小白到大牛》(第2版)关东升 编著
文章创作不易,本文10000+字,为了大家能理解,写的很详细,这也让我花了很多时间。最后,如果觉得本文对大家有帮助的话,还请给我点个赞和关注,谢谢大家!!!