Python PyMySQL操作MySQL数据库的方法详解
作者:CodeDevMaster
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的资料请关注脚本之家其它相关文章!