Python中数据库操作pymysql和 sqlalchemy

news/2024/5/27 17:25:50/ 标签: 数据库, python, mysql

python中操作mysql数据库,主要用到两个库,pymysql和 sqlalchemy。分别进行介绍

安装

安装没啥好说的,其实就是pip install就完事

python">pip install pymysql
pip install sqlalchemy

pymsql操作数据库

创建连接

以下语句省略了import语句,请自行import

要操作数据库,首先需要创建和数据库的连接,然后才能进程CRUD的操作。

python"># pymysql用connect方法进行连接
conn = pymysql.connect(host="192.168.32.11", port=3306,user="hellokitty", password="123123",database="hrs", charset="utf8mb4")

插入数据Create

python">no = int(input('部门编号: '))
name = input('部门名称: ')
location = input('部门所在地: ')
try:  # 2.获取游标对象with conn.cursor() as cursor:# 3.通过游标对象对数据库服务器发出sql语句affected_rows = cursor.execute(f"insert into `tb_dept` values (%s,%s,%s)",(no, name, location))if affected_rows == 1:print("新增部门成功")# 4.提交conn.commit()
except pymysql.MySQLError as err:# 4.回滚conn.rollback()print(type(err), err)
finally:# 5.关闭连接conn.close()

插入多组可以参考如下:

python">with conn.cursor() as cursor:affected_rows = cursor.executemany('insert into `tb_dept` values (%s, %s, %s)',[(no, name, location),(no1, name1, location1),(no2, name2, location2)])if affected_rows == 3:print('新增部门成功!!!')conn.commit()

删除delete

该例子中指定了一个参数:autocommit=True,这样SQL代码就会自动提交。实际环境中不建议这样做。

python">no = int(input("请输入部门编号:"))conn = pymysql.connect(host="192.168.32.11", port=3306,user="hellokitty", password="123123",database="hrs", charset="utf8mb4",autocommit=True)
try:with conn.cursor() as cursor:affected_rows = cursor.execute("delete from `tb_dept` where `dno`=%s",(no,))if affected_rows == 1:print("删除部门成功")
finally:conn.close()

更新update

python">no = int(input('部门编号: '))
name = input('部门名称: ')
location = input('部门所在地: ')try:with conn.cursor() as cursor:affected_rows = cursor.execute("update `tb_dept` set `dname`=%s, `dloc`=%s where `dno`=%s",(name, location, no))if affected_rows == 1:print("更新部门信息成功")conn.commit()
except pymysql.MySQLError as err:conn.rollback()print(type(err), err)
finally:conn.close()

查询数据

python">try:with conn.cursor() as cursor:affected_rows = cursor.execute("select `dno`,`dname`,`dloc` from `tb_dept`")row = cursor.fetchone()while row:print(row)row = cursor.fetchone()
except pymysql.MySQLError as err:conn.rollback()print(type(err), err)
finally:conn.close()

本例子中,使用while循环每次用fetchone获取一条数据然后打印。也提供了fetchall方法可以获取到所有的结果,但是不推荐这样做,因为在实际环境中这样对内存的压力很大。

默认拿到的是元组,如果希望拿到列表,需要在连接数据库时指定cursorclass=DictCursor

mysql_139">pymysql的缺陷

通过以上例子应该可以看出来,实际上pymysql操作数据库就是通过执行sql语句来的。通过拼接字符串的方式写好sql语句,然后交给pymysql执行。这种方式的缺点是显而易见的:

  1. sql语句比较长的时候很不方便
  2. 可能会有sql注入的危险
  3. 不太优雅

为了解决这些问题,可以使用sqlalchemy库

使用sqlalchemy库操作数据库

sqlalchemy创建数据库连接

首先用create_engine方法创建数据库引擎,然后再用connect方法连接。这里要稍微注意以下,第一个参数数据库的URI这里,不像pymysql直接输入就可以了,比如说pwd_alchemy = 'abc%401234’,这里实际密码是abc@1234,但不能直接输入@,需转换成%40。

python">from sqlalchemy import create_engine
# 创建连接
engine = create_engine(DB_URI,  # "mysql+pymysql://{USERNAME}:{pwd_alchemy}@{HOST}:{PORT}/{DATABASE}?charset=utf8mb4",echo=False,  # echo 设为 True 会打印出实际执行的 sql,调试的时候更方便future=True,  # 使用 SQLAlchemy 2.0 API,向后兼容pool_size=5,  # 连接池的大小默认为 5 个,设置为 0 时表示连接无限制pool_recycle=3600,  # 设置时间以限制数据库自动断开
)with engine.connect() as conn:......

执行sql语句

sqlalchemy也可以通过执行sql语句的方式操作数据库,这部分和pymysql区别不大。但是execute方法执行的sql语句,需要用sqlalchemy的text方法进行封装,这一点需要注意。

python">from sqlalchemy import textsql_text = "select * from tb_keys"
with engine.connect() as conn:result = conn.execute(text(sql_text))# 查询结果result类似生成器, 只能遍历一遍, 遍历第二遍时就是空数据# print(result.all())res = result.all()# result可以遍历,每一行是一个row对象,类似具名元祖(namedtuple),支持以下2种遍历方式
for row in res:print(row.keys_id, row.keys_name, row.keys_count)  # 通过字段名获取# print(row[0], row[1], row[2])  # 通过索引获取

顺便执行多条的语句,也很类似

python"># with engine.connect() as conn:
#     data = [{"keys_id": 11, "keys_name": 'test1', "keys_count": 1},
#             {"keys_id": 12, "keys_name": 'test2', "keys_count": 1}]
#     conn.execute(
#         text("INSERT INTO tb_keys (keys_id, keys_name, keys_count) VALUES (:keys_id, :keys_name, :keys_count)"),
#         data
#     )
#     # 手动commit
#     conn.commit()

声明式API

接下来重点说明一下sqlalchemy的声明式API。这就相当于直接创建一个Table对象,如下所示。

python">from sqlalchemy.orm import DeclarativeBase, Sessionclass Base(DeclarativeBase):"""DeclarativeBase无法直接使用,所以要先继承一个Base类"""passclass TableCount(Base):__tablename__ = "tb_keys"keys_id: Mapped[int] = mapped_column(Integer, primary_key=True)keys_name: Mapped[str] = mapped_column(String(30), index=True)keys_count: Mapped[int] = mapped_column(Integer)

我这张表结果很简单,表名是tb_keys,然后id,name,count3个字段,分别是主键、字符串和int类型。

用声明式api进行增删改查

然后是增删改查的例子:

python">from sqlalchemy import select, update# 用声明式API进行select查找,而不是直接执行sql语句
with Session(engine) as session:stmt = select(TableCount).where(TableCount.keys_count == 1).order_by(TableCount.keys_id)result = session.execute(stmt)# 一般情况下,当选取整个对象的时候,都要用 scalars 方法res2 = result.scalars()for row in res2:print(row.keys_id, row.keys_name, row.keys_count)print("*" * 40)# 查询单个属性,不需要用res3 = session.execute(select(TableCount.keys_name))for row in res3:print(row.keys_name)print("*" * 40)# 查询主键有一个快捷方式,以下查询id是7key_word = session.get(TableCount, 7)print(key_word.keys_name)# 更新数据使用updatestmt = update(TableCount).where(TableCount.keys_name == "护士").values(keys_name="护师").\execution_options(synchronize_session="fetch")session.execute(stmt)# 也可以直接修改值,比如上面获取到的key_word.keys_name = "Nurse"session.commit()# 注意,以下两种方式都能更新count值,但更推荐第二种做法。第一种方式可能会导致竞争更新,race condition(竞态条件# key_word.keys_count += 1key_word.keys_count = TableCount.keys_count + 1session.commit()# 新增# new_word = TableCount()# new_word.keys_count = 0# new_word.keys_name = "Alice"# session.add(new_word)# session.commit()# 删除, 用session.delete 删除,先获取到id,在get到该对象,然后用session.delete删除del_word = session.execute(select(TableCount.keys_id).where(TableCount.keys_name == 'Alice')).fetchone()del_word_id = del_word[0]del_word_obj = session.get(TableCount, del_word_id)session.delete(del_word_obj)session.commit()

完整代码请参考:https://github.com/h-kayotin/hanayo_hr/blob/master/hanayo_hr/db_sqlalchemy.py


http://www.ppmy.cn/news/1461853.html

相关文章

计算机网络-负载均衡算法

计算机网络中的负载均衡算法是决定如何将请求分发到各个服务器的关键。目前负载均衡算法主要分为静态负载均衡算法和动态负载均衡算法,具体包括以下几种: 静态负载均衡算法: 1.轮询法(Round Robin):按照顺…

Ardupilot Rpanion iperf网络性能测试

Ardupilot Rpanion iperf网络性能测试 1. 源由2. 分析3. 安装4. 测试4.1 第一次测试4.1.1 iperf测试参数A4.1.1.1 测试链路14.1.1.2 测试链路24.1.1.3 测试链路3 4.1.2 iperf测试参数B - 测试链路34.1.2.1 测试数据4.1.2.2 数据简单分析4.1.2.3 数据深入分析4.1.2.4 模拟测试网…

element-plus 工作经验总结

Element-plus 文章目录 Element-plus忠告: 最好锁定版本, 免得更新更出 BUG 来了el-drawer 设置 modal"false" 后, 遮罩元素仍存在, 点不了空白的地方el-tree 大数据量时接收 check-change 事件报错导致涉及多个节点的操作没执行完毕el-table 表头 show-overflow-too…

Linux---编辑器vim的认识与简单配置

前言 我们在自己的电脑上所用的编译软件,就拿vs2022来说,我们可以在上面写C/C语言、python、甚至java也可以在上面进行编译,这种既可以用来编辑、运行编译,又可以支持很多种语言的编译器是一种集成式开发环境,集众多于…

软件设计师笔记和错题

笔记截图 数据库 模式是概念模式 模式/内模式 存在概念级和内部级之间,实现了概念模式和内模式的互相转换 外模式/模式映像 存在外部级和概念级之间,实现了外模式和概念模式的互相转换。 数据的物理独立性, 概念模式和内模式之间的映像…

WordPress原创插件:超链接点击访问统计

WordPress原创插件:超链接点击访问统计 https://download.csdn.net/download/huayula/89296775

DockerFile介绍与使用

一、DockerFile介绍 大家好,今天给大家分享一下关于 DockerFile 的介绍与使用,DockerFile 是一个用于定义如何构建 Docker 镜像的文本文件,具体来说,具有以下重要作用: 标准化构建:提供了一种统一、可重复…

Shell脚本——批量清理Kubernetes集群中Evicted状态的pod

测试环境有一台宿主机出现了异常,大量的异常日志导致宿主机的磁盘使用率超过了85%,触发了上面的pod驱离策略,该宿主机上的的pod处于Evicted状态。在清理了磁盘之后,得手动处理掉这些Evicted状态的pod。 #!/bin/bash# 获取当前状态…

HCIP【VLAN综合实验】

目录 一、实验拓扑图: 二、实验要求: 三、实验思路: 四、实验步骤: 1、在交换机SW1,SW2,SW3配置VLAN和各个接口对应类型的配置 2、在路由器上面配置DHCP服务 一、实验拓扑图: 二、实验要求: 1、PC1 …

数据结构-二叉树-红黑树

一、红黑树的概念 红黑树是一种二叉搜索树,但在每个节点上增加一个存储位表示节点的颜色,可以是Red或者BLACK,通过对任何一条从根到叶子的路径上各个节点着色方式的限制,红黑树确保没有一条路径会比其他路径长出两倍,…

遥感数据集制作(Potsdam数据集为例):TIF图像转JPG,TIF标签转PNG,图像重叠裁剪

文章目录 TIF图像转JPGTIF标签转PNG图像重叠裁剪图像重命名数据集转COCO格式数据集转VOC格式 遥感图像不同于一般的自然图像,由于波段数量、图像位深度等原因,TIF图像数据不能使用简单的格式转换方法。本文以Potsdam数据集为例,制作能够直接用…

MongoDB聚合运算符:$trunc

MongoDB聚合运算符&#xff1a;$trunc 文章目录 MongoDB聚合运算符&#xff1a;$trunc语法参数字段 使用返回的数据类型null, NaN, 和 正/负无穷 举例 $trunc聚合运算符用于将数字截断为整数或指定的小数位。 语法 { $trunc : [ <number>, <place> ] }参数字段 &…

SSM【Spring SpringMVC Mybatis】—— Spring(一)

目录 1、初识Spring 1.1 Spring简介 1.2 搭建Spring框架步骤 1.3 Spring特性 1.5 bean标签详解 2、SpringIOC底层实现 2.1 BeanFactory与ApplicationContexet 2.2 图解IOC类的结构 3、Spring依赖注入数值问题【重点】 3.1 字面量数值 3.2 CDATA区 3.3 外部已声明be…

关键字详解

1.用于定义访问权限修饰符的关键字 面向对象程序三大特性&#xff1a;封装、继承、多态。 1.1 访问权限符 Java 中主要通过类和访问权限来实现封装&#xff1a; 类可以将数据以及封装数据的方法结合在一起 &#xff0c;更符合人类对事物的认知&#xff0c;而访问权限用来控制…

【一步一步了解Java系列】:了解Java与C语言的运算符的“大同小异”

看到这句话的时候证明&#xff1a;此刻你我都在努力~ 加油陌生人~ 个人主页&#xff1a; Gu Gu Study ​​ 专栏&#xff1a;一步一步了解Java 喜欢的一句话&#xff1a; 常常会回顾努力的自己&#xff0c;所以要为自己的努…

BERT for Joint Intent Classification and Slot Filling 论文阅读

BERT for Joint Intent Classification and Slot Filling 论文阅读 Abstract1 Introduction2 Related work3 Proposed Approach3.1 BERT3.2 Joint Intent Classification and Slot Filling3.3 Conditional Random Field 4 Experiments and Analysis4.1 Data4.2 Training Detail…

软件工程期末复习(7)需求过程

需求分析 需求过程 什么是需求过程&#xff1f; 需求过程是用来导出、确认和维护系统需求文档的一组结构化活动。通常&#xff0c;一个良好的需求过程应包括下列活动&#xff1a; 需求提取需求分析和协商需求确认 需求提取 需求提取是通过与客户、系统用户和其他与系统开发相…

Linux的常用指令 和 基础知识穿插巩固(巩固知识必看)

目录 前言 ls ls 扩展知识 ls -l ls -a ls -al cd cd 目录名 cd .. cd ~ cd - pwd 扩展知识 路径 / cp [选项] “源文件名” “目标文件名” mv [选项] “源文件名” “目标文件名” rm 作用 用法 ./"可执行程序名" mkdir rmdir touch m…

QMetaObject 是 Qt 框架中的一个重要类,用于在运行时处理对象的元对象信息

QMetaObject 是 Qt 框架中的一个重要类&#xff0c;用于在运行时处理对象的元对象信息。每个继承自 QObject 的类在 Qt 中都有一个对应的 QMetaObject&#xff0c;用于存储该类的元对象信息&#xff0c;包括类名、父类、信号和槽等。 以下是 QMetaObject 类的一些主要功能和用…

ubuntu24.04安装ros

ubuntu24.04安装ros 踩坑 踩坑 目前安装人数比较少&#xff0c;没有较为详细的博客&#xff0c;参考官网的链接 http://docs.ros.org/en/rolling/Installation/Ubuntu-Install-Debians.html 同时在如下的一步中会找不到网址报错&#xff0c;此时可以参考https://blog.51cto.c…