PyMySQL是一个用于Python编程语言的纯Python MySQL客户端库,它实现了MySQL数据库协议的所有版本,并支持多线程应用程序和Python 3.x版本。PyMySQL遵循Python标准DB API接口,并提供了许多方便的功能,如MySQL连接池、SSL/TLS加密连接、SQL注入预防等。
GitHub:https://github.com/PyMySQL/PyMySQL
安装PyMySQL库
pip3 install pymysql
查看第三方包的信息
pip3 show pymysql
查看安装的第三方包列表
pip3 list
导入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,'[email protected]'); '''
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,'[email protected]')" % 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语句的语义,最终产生数据泄露的现象。
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'))