数据库编程

数据库

数据库(Database)是计算机系统中用于存储、管理和访问数据的核心组件,也被称为数据存储库(Data Store)。以下是对数据库的详细解释:

一、定义与基本概念

  • 定义:数据库是指存储数据的容器,它能够存储大量结构化和非结构化的数据,包括文本、数字、图像、音频等各种类型的数据。
  • 基本概念:数据库由若干个相关数据的集合组成,这些数据被组织在表格、集合或其他数据结构中,以便于进行高效的管理、处理和访问。

二、数据库的类型

  1. 关系型数据库:使用表格(二维结构)来组织和存储数据,通过结构化查询语言(SQL)进行数据管理和查询。常见的关系型数据库包括MySQL、Oracle Database、Microsoft SQL Server、PostgreSQL等。
  2. 非关系型数据库(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+字,为了大家能理解,写的很详细,这也让我花了很多时间。最后,如果觉得本文对大家有帮助的话,还请给我点个赞和关注,谢谢大家!!!

相关推荐
白鲸开源7 小时前
(二)从分层架构到数据湖仓架构:数据仓库分层下的技术架构与举例
大数据·数据库·数据分析
好玩的Matlab(NCEPU)7 小时前
Redis vs RabbitMQ 对比总结
数据库·redis·rabbitmq
21号 17 小时前
16.MySQL 服务器配置与管理
服务器·数据库·mysql
我的offer在哪里7 小时前
MongoDB
数据库·mongodb
练习时长一年9 小时前
AI开发结构化输出
数据库
IvorySQL9 小时前
灾难恢复工具内核细节探究与分享
数据库·postgresql·开源
lypzcgf9 小时前
商城小程序数据库表结构文档
数据库·小程序·电商
jjw_zyfx9 小时前
Ubuntu上vue3 vite使用MBTiles搭建地图服务器
服务器·数据库·ubuntu
EndingCoder9 小时前
Node.js SQL数据库:MySQL/PostgreSQL集成
javascript·数据库·sql·mysql·postgresql·node.js
静听山水10 小时前
SQLite
数据库·sqlite