python

关注公众号 jb51net

关闭
首页 > 脚本专栏 > python > PyMySQL操作MySQL

Python PyMySQL操作MySQL数据库的方法详解

作者:CodeDevMaster

PyMySQL是一个用于Python编程语言的纯Python MySQL客户端库,它遵循Python标准DB API接口,并提供了许多方便的功能,本文就来和大家简单介绍一下吧

PyMySQL

PyMySQL概述

PyMySQL是一个用于Python编程语言的纯Python MySQL客户端库,它实现了MySQL数据库协议的所有版本,并支持多线程应用程序和Python 3.x版本。PyMySQL遵循Python标准DB API接口,并提供了许多方便的功能,如MySQL连接池、SSL/TLS加密连接、SQL注入预防等。

GitHub:https://github.com/PyMySQL/PyMySQL

安装PyMySQL库

安装PyMySQL库

pip3 install pymysql

查看第三方包的信息

pip3 show pymysql 

查看安装的第三方包列表

pip3 list 

PyMySQL的基本使用

API介绍

导入PyMySQL库

import pymysql

使用PyMySQL建立与MySQL数据库的连接

pymysql.connect(参数列表)
connect_db = pymysql.connect(host='localhost', port=3306, user='root', password='123456', database='demo')

获取游标对象

cursor =conn.cursor()

执行SQL语句

row_count = cursor.execute(sql)

获取查询结果集

result = cursor.fetchall()

将修改操作提交到数据库

conn.commit()

回滚数据

conn.rollback()

关闭游标

cursor.close()

关闭连接

conn.close()

查询操作

# 导包
import pymysql
# 创建数据库连接对象
# 连接数据库时,除端口参数外,其余参数都要使用字符串类型指定
# host:连接的mysql主机,如果本机是'localhost'
# port:连接的mysql主机的端口,默认是3306
# user:连接的用户名
# password:连接的密码
# database:数据库的名称
# charset:通信采用的编码方式,推荐使用utf8
connect_db = pymysql.connect(host='localhost', port=3306, user='root', password='123456', charset='utf8', database='demo')
# 获取游标对象
# 一个数据库连接对象,可以创建多个游标对象
# 一般情况下,同一时刻,只会建立一个进行操作
# 游标对象在创建的时候,默认会开启一个事务环境
cur = connect_db.cursor()
# 写SQL语句
sql_str = '''select * from item'''
# 执行SQL语句
row_count = cur.execute(sql_str)
print(f'查询到 {row_count} 条记录')
print()
# 获取一条查询结果
result = cur.fetchone()
print(result)
print()
# 获取指定条数的记录
result = cur.fetchmany(4)
for t in result:
    print(t)
print()
# 获取所有数据
result = cur.fetchall()
for t in result:
    print(t)
print()
# 移动游标的属性
cur.rownumber = 0
result = cur.fetchall()
print(cur.rowcount)
for t in result:
    print(t)
# 关闭游标对象
cur.close()
# 关闭数据库对象
connect_db.close()
查询到 10 条记录
(1, datetime.datetime(2022, 8, 21, 19, 31, 11), 'https:////img13.360buyimg.com/n1/s450x450_jfs/t1/175088/12/11173/264547/60aa5dd6Efe2b408b/b91c5bdaf6918ffa.jpg', 4299.0, '联想京东自营旗舰店', 'i5 16G 背光键盘', ' 联想笔记本电脑 小新Air14 英特尔酷睿i5 14英寸轻薄本(i5 16G 512G 高色域 大电池)银 全面屏商务办公本 ', 'https://item.jd.com/100011483893.html')
(2, datetime.datetime(2022, 8, 21, 19, 31, 11), 'https:////img13.360buyimg.com/n1/s450x450_jfs/t1/113403/25/29544/70492/6302023dE572552c8/e7c452efb3616b70.jpg', 4999.0, '联想京东自营旗舰店', 'i5 16G 背光键盘', '  联想笔记本电脑小新Pro14 英特尔Evo平台 14英寸游戏轻薄本(标压i5 16G 512G 2.8K 90Hz护眼屏)全面屏办公本 ', 'https://item.jd.com/100014546493.html')
(3, datetime.datetime(2022, 8, 21, 19, 31, 11), 'https:////img12.360buyimg.com/n1/jfs/t1/219048/2/15799/192377/623ed1d3Eb52b150d/f669f9891c915da0.jpg', 2798.0, 'HUWI旗舰店', '16G运行+1024G超速硬盘', ' HUWI 国行【2022款英特尔可选酷睿】金属笔记本电脑轻薄本大学生上网课设计学习商务办公游戏手提 玫瑰金-高配英特尔四核12代+IPS屏窄边全面屏 16G运行+1024G超速硬盘 ', 'https://item.jd.com/10044527344297.html')
(4, datetime.datetime(2022, 8, 21, 19, 31, 11), 'https:////img12.360buyimg.com/n1/s450x450_jfs/t1/42776/10/17345/131277/626bc1e3Eb2b0278a/1dc51316f3dc1898.jpg', 4799.0, '华为京东自营官方旗舰店', 'i5 16G 512G 皓月银', ' 华为笔记本电脑MateBook D 14 2022款 14英寸 11代酷睿 i5 16G+512G 锐炬显卡 轻薄本/护眼全面屏 银 ', 'https://item.jd.com/100016960357.html')
(5, datetime.datetime(2022, 8, 21, 19, 31, 11), 'https:////img14.360buyimg.com/n1/s450x450_jfs/t1/69468/27/17416/141766/626baaecE202ac55d/d65dd608458c8c0b.jpg', 3999.0, '华为京东自营官方旗舰店', 'i5 8GB 512GB 皓月银', '  华为笔记本电脑MateBook D 14 SE版 14英寸 11代酷睿 i5 锐炬显卡 8G+512G 轻薄本/高清护眼防眩光屏 银 ', 'https://item.jd.com/100032149194.html')
(6, datetime.datetime(2022, 8, 21, 19, 31, 11), 'https:////img14.360buyimg.com/n1/s450x450_jfs/t1/99321/22/30610/122437/62ac48e7Eaf3ef4ac/464d0f1f132c8d62.jpg', 9299.0, '惠普(HP)OMEN暗影精灵京东自营旗舰店', '【新12代i7】满血3060+2K屏版', ' 惠普(HP)暗影精灵8Pro 16.1英寸游戏笔记本电脑(12代酷睿i7-12700H RTX3060 6G 16GDDR5 512G 2.5K 165Hz) ', 'https://item.jd.com/100021389129.html')
(7, datetime.datetime(2022, 8, 21, 19, 31, 17), 'https:////img12.360buyimg.com/n1/jfs/t1/47859/1/18224/153861/62a45618E5078f925/534299d323f12a2c.jpg', 1358.0, '智能驼数码旗舰店', '8G内存+128G固态硬盘', ' 【2022款英特尔+酷睿i7】15.6英寸笔记本电脑轻薄本网课设计学习商务办公游戏大学生手提 智能驼 青春版【11代英特尔】全面屏+抗蓝光 8G内存+128G固态硬盘 ', 'https://item.jd.com/10033087405727.html')
(8, datetime.datetime(2022, 8, 21, 19, 31, 17), 'https:////img11.360buyimg.com/n1/s450x450_jfs/t1/195842/2/20561/168501/62ca4248Edde4fefe/bbe877dbc201290e.jpg', 5699.0, 'ThinkPad京东自营旗舰店', 'i5-12500H 2.8K 90Hz', ' 联想ThinkBook 14+ 英特尔酷睿i5 笔记本电脑全新2022款 14英寸标压轻薄本i5-12500H 16G 512G 2.8K 90Hz ', 'https://item.jd.com/100020078921.html')
(9, datetime.datetime(2022, 8, 21, 19, 31, 17), 'https:////img11.360buyimg.com/n1/s450x450_jfs/t1/115135/13/26808/193275/62f371acE21c52747/20f36c3f88327703.jpg', 5399.0, '惠普京东自营官方旗舰店', '【五代 新】i5 16G 512 高色域', '  惠普(HP)战66 五代 14英寸轻薄笔记本电脑(英特尔12代酷睿 i5-1240P 16G 512G 高色域低功耗屏 1年上门) ', 'https://item.jd.com/100020480561.html')
(10, datetime.datetime(2022, 8, 21, 19, 31, 17), 'https:////img12.360buyimg.com/n1/s450x450_jfs/t1/7498/9/18671/72563/62fb8cc2E2a4bedc8/cf134acbac78ec40.jpg', 3999.0, '小米京东自营旗舰店', 'R5 16G 512G', '  小米 RedmiBookPro 14英寸 2.5K高色域视网膜屏 轻薄笔记本电脑(6核R5 16G 512G-SSD 指纹识别 DC调光) ', 'https://item.jd.com/100011526087.html')

插入操作

# 导包
import pymysql
# 连接数据库
connect_db = pymysql.connect(host='localhost', port=3306, user='root', password='123456', charset='utf8', database='demo')
# 获取游标对象
cur = connect_db.cursor()
# 执行sql
sql_str = '''insert into tb_user(id ,user_name,password,name,age,email) values(null,'0001','123456','Jack',20,'123456789@qq.com'); '''
cur.execute(sql_str)
# 当在对数据库做增删改时,默认会在事务环境中进行操作,操作完成后要进行手动提交操作,如果不提交,程序默认操作为回滚
connect_db.commit()
# 关闭游标对象
cur.close()
# 关闭数据库连接
connect_db.close()

批量插入操作

def main():
    # 创建Connection连接
    conn = pymysql.connect(host='localhost', port=3306, user='root', password='123456', charset='utf8', database='demo')
    # 获得Cursor对象
    cursor = conn.cursor()
    # 插入1万次数据
    for i in range(10000):
        cursor.execute("insert into tb_user values(null,'000%d','123456','Jack',20,'123456@qq.com')" % i)
    # 提交数据
    conn.commit()
if __name__ == "__main__":
    main()

删除操作

import pymysql
# 连接数据库
connect_db = pymysql.connect(host='localhost', port=3306, user='root', password='123456', charset='utf8', database='demo')
# 获取游标对象
cur = connect_db.cursor()
sql_str = ''' delete from tb_user where user_name = '0001' '''
# 执行sql
cur.execute(sql_str)
# 提交
connect_db.commit()
# 关闭游标对象
cur.close()
# 关闭数据库连接
connect_db.close()

更新操作

import pymysql
# 连接数据库
connect_db = pymysql.connect(host='localhost', port=3306, user='root', password='123456', charset='utf8', database='demo')
# 获取游标对象
cur = connect_db.cursor()
# 执行sql
sql_str = ''' update tb_user set password = '12345' where user_name = '0001' '''
cur.execute(sql_str)
# 提交
connect_db.commit()
# 关闭游标对象
cur.close()
# 关闭数据库连接
connect_db.close()

SQL注入

什么是SQL注入

用户提交带有恶意的数据与SQL语句进行字符串方式的拼接,从而影响SQL语句的语义,最终产生数据泄露的现象。

import pymysql
connect_db = pymysql.connect(host='localhost', port=3306, user='root', password='123456', charset='utf8', database='demo')
cur = connect_db.cursor()
select_id = input('请输入一个查询ID:')
sql_str = ''' select * from tb_user where id = %s ''' % select_id
print(sql_str)
cur.execute(sql_str)
result = cur.fetchall()
print(result)
cur.close()
connect_db.close()

利用sql的合法规则 ,查询到了不应该得到的数据,也就称为SQL注入

请输入一个查询ID: 1 or 1=1
 select * from tb_user where id = 1 or 1=1 
((1, 'zhangsan', '123456', '小白', 20, 'test1@qq.com'), (2, 'lisi', '123456', '李四', 20, 'test2@qq.com'), (3, 'wangwu', '123456', '王五', 28, 'test3@qq.com'))

解决方案

SQL语句参数化,即SQL语言中的参数使用%s来占位,将SQL语句中%s占位所需要的参数存在一个列表中,把参数列表传递给execute方法中第二个参数

sql_str = ''' select * from tb_user where id = %s ''' % select_id
print(sql_str)
# 利用execute方法的第二个参数,解决SQL注入的问题
cur.execute(sql_str, (select_id,))

请输入一个查询ID: 1 or 1=1
 select * from tb_user where id = %s 
((1, 'zhangsan', '123456', '小白', 20, 'test1@qq.com'),)

注意事项

保护敏感信息

在连接数据库时,不要把敏感信息(例如用户名和密码)直接硬编码到代码中。而是应该将这些敏感信息存储在安全的方式中,例如配置文件或环境变量中,并在代码中动态加载。

1.创建config.ini的INI配置文件

[mysql]
user=root
password=123456
host=localhost
port=3306
database=mydb

2.读取配置文件

ConfigParser 是 Python 标准库中的一个模块,它用于读取和解析INI格式的配置文件。可以使用该模块轻松地读取配置文件并将其加载到Python程序中进行进一步处理。

from configparser import ConfigParser
# 读取配置文件
config = ConfigParser()
config.read('config.ini')
# 获取MySQL登录凭据
MYSQL_USER = config.get('mysql', 'user')  # 输出:root
MYSQL_PASSWORD = config.get('mysql', 'password')
# 连接MySQL数据库
db = mysql.connector.connect(host='127.0.0.1',
                             user=MYSQL_USER,
                             password=MYSQL_PASSWORD,
                             database='mydb')

使用连接池

在高负载情况下,频繁地创建和释放数据库连接会降低性能并增加系统开销。因此,建议使用连接池来管理数据库连接,以便在需要时从连接池获得可用连接,并在使用后将其返回到池中。

使用连接池有助于优化数据库连接的管理和复用,并减少了每个请求或操作启动新连接的开销,从而提高了系统的性能和响应速度。

1.安装PyMySQL库和pymysql-pool库

pip install pymysql
pip install pymysql-pool

2.导入PyMySQL库和连接池模块。

import pymysql
from pymysqlpool import ConnectionPool

3.创建连接池对象并指定连接参数

db_config = {
    'max_connections': 10,
    'max_idle_time': 60,
    'host': 'localhost',
    'port': 3306,
    'user': 'root',
    'password': 'password',
    'database': 'mydb'
}
pool = ConnectionPool(**db_config)

4.获取连接对象和游标,并执行SQL语句

with pool.get_conn() as conn:
    with conn.cursor() as cur:
        sql = "SELECT * FROM mytable WHERE name=%s"
        cur.execute(sql, ('John',))
        results = cur.fetchall()
        print(results)

5.关闭游标和连接,并归还连接到连接池

cur.close()
pool.return_conn(conn)

异常处理

在与数据库进行交互时,出错是不可避免的。在产生异常时,需要及时捕获和处理异常,以避免程序崩溃或泄露敏感信息。

try:
    # 操作数据库
except Exception as e:
    print("Error:", e)
    # 处理异常
finally:
    # 关闭连接和游标
    cur.close()
    conn.close()

防止并发冲突

在多个进程或线程同时访问和修改同一个数据时,可能会出现并发冲突,导致数据不一致或错误。为此,建议使用数据库的事务支持来确保数据的一致性和正确性

try:
    # 开始事务
    conn.begin()
    # 操作数据库
    # 提交事务
    conn.commit()
except Exception as e:
    print("Error:", e)
    # 回滚事务
    conn.rollback()
finally:
    # 关闭连接和游标
    cur.close()
    conn.close()

优化查询

查询数据时,应尽可能减少查询次数,可以通过使用索引、批量插入等方法优化和加速查询。此外,在INSERT、UPDATE和DELETE语句中,应使用参数化查询来防止SQL注入攻击。

# 参数化SQL查询
sql = "SELECT * FROM tablename WHERE column1 = %s AND column2 = %s"
cur.execute(sql, ('value1', 'value2'))

以上就是Python PyMySQL操作MySQL数据库的方法详解的详细内容,更多关于PyMySQL操作MySQL的资料请关注脚本之家其它相关文章!

您可能感兴趣的文章:
阅读全文