文章目录
- 一.安装
- 二.pymysql参数介绍
- 三.pymsql实操
- 3.1 通过pymsql实现增删改查MySQL数据
- 3.2 通过pymsql实现将csv数据录入到mysql
- 3.2.1 一个insert+update例子
- 3.2.2 csv空值处理
- 3.3 通过pymysql将本地mysql数据迁移到远程mysql
- 参考
一.安装
Python3.x 如果想连接MySQL需要安装 pymysql 模块。
pymysql 模块可以通过 pip 安装。
pip install pymysql
二.pymysql参数介绍
pymysql的参数如下:
#创建数据库连接pymysql.Connect()参数说明
host(str): MySQL服务器地址
port(int): MySQL服务器端口号
user(str): 用户名
passwd(str): 密码
db(str): 数据库名称
charset(str): 连接编码,存在中文的时候,连接需要添加charset='utf8',否则中文显示乱码。
connection对象支持的方法
cursor() 使用该连接创建并返回游标
commit() 提交当前事务,不然无法保存新建或者修改的数据
rollback() 回滚当前事务
close() 关闭连接
cursor对象支持的方法
execute(op) 执行SQL,并返回受影响行数
fetchone() 取得结果集的下一行
fetchmany(size) 获取结果集的下几行
fetchall() 获取结果集中的所有行
rowcount() 返回数据条数或影响行数
close() 关闭游标对象
三.pymsql实操
3.1 通过pymsql实现增删改查MySQL数据
如需要scott用户下建表及录入数据语句,可参考:
scott建表及录入数据sql脚本
下面是测试通过pymysql来对mysql进行增删改查以及事物。
代码:
db_setting.py
# 存储数据库信息
# 创建一个列表嵌套列表,存储数据库信息
# 依次是 数据库备注、ip、端口、、用户名、密码、登陆数据库名
mysql_msg = [['本地mysql', 'localhost', 3306 , 'root', 'abc123', 'zqs'],
['远程mysql', '10.31.1.123', 3306, 'root', 'abc123', 'test']
]
mysql_test1.py
import pymysql, datetime
import db_setting
class mysql_class(object):
"""对mysql的操作创建一个类"""
def __init__(self, name):
self.name = name
def login_mysql(self):
"""获取mysql的登陆信息"""
mysql_msg = db_setting.mysql_msg
name = self.name
for i in range(0,len(mysql_msg) ):
exec_db = mysql_msg[i]
if name == exec_db[0]:
# 根据输入连接数据库
return exec_db
# conn = pymysql.connect(host=exec_db[1], port=exec_db[2], user=exec_db[3], passwd=exec_db[4],db=exec_db[5])
else:
pass
def insert_mysql(self, datas):
"""往bonus表录入数据"""
exec_db = mysql_class.login_mysql(self)
conn = pymysql.connect(host=exec_db[1], port=exec_db[2], user=exec_db[3], passwd=exec_db[4], db=exec_db[5])
cursor = conn.cursor()
sql1 = "insert into bonus(ename, job, sal, comm ) values ('%s', '%s', %.2f, %.2f)"
# 遍历列表,循环录入数据
for data in datas:
cursor.execute(sql1 % data)
print('成功插入', cursor.rowcount, '条数据')
conn.commit()
# 关闭连接
cursor.close()
conn.close()
def update_mysql(self, datas):
"""更改bonus表数据"""
exec_db = mysql_class.login_mysql(self)
conn = pymysql.connect(host=exec_db[1], port=exec_db[2], user=exec_db[3], passwd=exec_db[4], db=exec_db[5])
cursor = conn.cursor()
sql1 = "update bonus set comm = %.2f where ename = '%s' "
# 遍历列表,循环更改数据
for data in datas:
cursor.execute(sql1 % data)
print('成功修改', cursor.rowcount, '条数据')
conn.commit()
# 关闭连接
cursor.close()
conn.close()
def select_mysql(self, datas):
"""查询bonus表数据"""
exec_db = mysql_class.login_mysql(self)
conn = pymysql.connect(host=exec_db[1], port=exec_db[2], user=exec_db[3], passwd=exec_db[4], db=exec_db[5])
cursor = conn.cursor()
sql1 = "select ename,comm from bonus where ename = '%s' "
# 遍历列表,循环查询数据
for data in datas:
cursor.execute(sql1 % data)
for row in cursor.fetchall():
print("ename:%s\tcomm:%.2f" % row)
print('共查找出', cursor.rowcount, '条数据')
conn.commit()
# 关闭连接
cursor.close()
conn.close()
def transaction_mysql(self, datas):
""" 测试mysql的事务 """
exec_db = mysql_class.login_mysql(self)
conn = pymysql.connect(host=exec_db[1], port=exec_db[2], user=exec_db[3], passwd=exec_db[4], db=exec_db[5])
cursor = conn.cursor()
sql1 = "update bonus set comm = %.2f where ename = '%s' "
sql2 = "update emp set comm = %.2f where ename = '%s' "
try:
# 遍历列表,循环更改数据
for data in datas:
cursor.execute(sql1 % data)
cursor.execute(sql2 % data)
print('成功修改', cursor.rowcount, '条数据')
except Exception as e:
conn.rollback() # 事务回滚
print('事务处理失败', e)
else:
conn.commit() # 事务提交
print('事务处理成功', cursor.rowcount)
# 关闭连接
cursor.close()
conn.close()
def delete_mysql(self, datas):
"""删除bonus表数据"""
exec_db = mysql_class.login_mysql(self)
conn = pymysql.connect(host=exec_db[1], port=exec_db[2], user=exec_db[3], passwd=exec_db[4], db=exec_db[5])
cursor = conn.cursor()
sql1 = "delete from bonus where ename = '%s' "
# 遍历列表,循环删除数据
for data in datas:
cursor.execute(sql1 % data)
print('成功删除', cursor.rowcount, '条数据')
conn.commit()
# 关闭连接
cursor.close()
conn.close()
# 这里才是主程序
if __name__ == '__main__':
my_class1 = mysql_class('本地mysql')
# 插入多条数据
my_class1.insert_mysql([('SMITH', 'ClERK', 800, 100),('ALLEN', 'SALESMAN', 1600, 500)])
# 更改多条数据
my_class1.update_mysql([(200, 'SMITH'), (600, 'ALLEN')])
# 查询多条数据
my_class1.select_mysql((('SMITH'),('ALLEN')))
# 事务
my_class1.transaction_mysql([(300, 'SMITH'), (700, 'ALLEN')])
# 删除多条数据
my_class1.delete_mysql([('SMITH'),('ALLEN')])
测试记录:
E:\python\learn_python1\venv\Scripts\python.exe E:/python/learn_python1/mysql_test1.py
成功插入 1 条数据
成功插入 1 条数据
成功修改 1 条数据
成功修改 1 条数据
ename:SMITH comm:200.00
共查找出 1 条数据
ename:ALLEN comm:600.00
共查找出 1 条数据
成功修改 1 条数据
成功修改 1 条数据
事务处理成功 1
成功删除 1 条数据
成功删除 1 条数据
Process finished with exit code 0
3.2 通过pymsql实现将csv数据录入到mysql
生产环境中,我们经常会遇到将csv的数据录入到mysql数据库,类似navicat、mysql workbench等可视化工具提供了excel导入到数据库的功能,但是有时候会报错,本次我们来通过案例讲解将csv的数据录入到mysql。
3.2.1 一个insert+update例子
csv文件:
E:\python\file_test>more emp_csv.csv
"empno","ename","job","mgr","hiredate","sal","comm","deptno"
"7369","SMITH","CLERK","7902","1980-12-17","800.00","300.00","20"
"7499","ALLEN","SALESMAN","7698","1981-02-20","1600.00","700.00","30"
"7521","WARD","SALESMAN","7698","1981-02-22","1250.00","500.00","30"
"7566","JONES","MANAGER","7839","1981-04-02","2975.00",,"20"
"7654","MARTIN","SALESMAN","7698","1981-09-28","1250.00","1400.00","30"
"7698","BLAKE","MANAGER","7839","1981-05-01","2850.00",,"30"
"7782","CLARK","MANAGER","7839","1981-06-09","2450.00",,"10"
"7788","SCOTT","ANALYST","7566","1987-06-13","3000.00",,"20"
"7839","KING","PRESIDENT",,"1981-11-17","5000.00",,"10"
"7844","TURNER","SALESMAN","7698","1981-09-08","1500.00","0.00","30"
"7876","ADAMS","CLERK","7788","1987-06-13","1100.00",,"20"
"7900","JAMES","CLERK","7698","1981-12-03","950.00",,"30"
"7902","FORD","ANALYST","7566","1981-12-03","3000.00",,"20"
"7934","MILLER","CLERK","7782","1982-01-23","1300.00",,"10"
用excel打开csv文件截图:
创建一个空的emp_csv表:
create table emp_csv like emp;
Python代码:
db_setting.py
# 存储数据库信息
# 创建一个列表嵌套列表,存储数据库信息
# 依次是 数据库备注、ip、端口、、用户名、密码、登陆数据库名
mysql_msg = [['本地mysql', 'localhost', 3306 , 'root', 'abc123', 'zqs'],
['远程mysql', '10.31.1.123', 3306, 'root', 'abc123', 'test']
]
mysql_test2.py
import pymysql, datetime
import csv
import db_setting
import math
from numpy import nan as NaN
class mysql_class(object):
"""对mysql的操作创建一个类"""
def __init__(self, name):
self.name = name
def login_mysql(self):
"""获取mysql的登陆信息"""
mysql_msg = db_setting.mysql_msg
name = self.name
for i in range(0,len(mysql_msg) ):
exec_db = mysql_msg[i]
if name == exec_db[0]:
# 根据输入连接数据库
return exec_db
# conn = pymysql.connect(host=exec_db[1], port=exec_db[2], user=exec_db[3], passwd=exec_db[4],db=exec_db[5])
else:
pass
def csv_insert_mysql(self):
"""将csv的文件录入到mysql"""
exec_db = mysql_class.login_mysql(self)
conn = pymysql.connect(host=exec_db[1], port=exec_db[2], user=exec_db[3], passwd=exec_db[4], db=exec_db[5] ,charset='utf8')
cursor = conn.cursor()
# sql1 = "insert into emp_csv(empno, ename, job, mgr, hiredate, sal, comm, deptno) values (%.2f, '%s', '%s', %.2f, '%s', %.2f, %.2f, %.2f)"
# 测试了数值类型还是会存在问题, yyyy/mm/dd 这类时间格式测试了也不会有问题的
sql1 = "insert into emp_csv(empno, ename, job, mgr, hiredate, sal, comm, deptno) values ('%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s') "
sql2 = "update emp_csv set mgr = null where empno = '%s' "
sql3 = "update emp_csv set comm = null where empno = '%s' "
filename = 'E:/python/file_test/emp_csv.csv'
with open(filename, 'r') as f:
reader = csv.reader(f)
# print(type(reader))
for i, row in enumerate(reader):
# 剔除第一行的列头
if i > 0:
# print(row)
row3 = tuple(row)
# 录入数值型空值会有问题,如遇到先改为0 后面再update
if row[3] == '':
row[3] = '0'
if row[6] == '':
row[6] = '0'
# 数据库执行的时候,要求是tuple而不是list,进行转换
row2 = tuple(row)
print(row2)
# 遍历列表,循环录入数据
cursor.execute(sql1 % row2)
# python对数值的空值处理还是存在问题,通过sql进行update吧
if row3[3] == '':
cursor.execute(sql2 % row3[0])
if row3[6] == '':
cursor.execute(sql3 % row3[0])
conn.commit()
# 关闭连接
cursor.close()
conn.close()
if __name__ == '__main__':
my_class1 = mysql_class('本地mysql')
my_class1.csv_insert_mysql()
3.2.2 csv空值处理
对于CSV中空值的处理
数值型空值,必须是 %s 而不能使用 ‘%s’
字符型空值以及时间类型空值,必须是 %s 而不能使用 ‘%s’,但是录入其它非空的字符,又必须用’%s’
用excel打开csv文件截图:
从上图可以看到 ename列是字符型空值,mgr、comm列是数值型空值,hiredate是日期型空值
Python代码:
db_setting.py
# 存储数据库信息
# 创建一个列表嵌套列表,存储数据库信息
# 依次是 数据库备注、ip、端口、、用户名、密码、登陆数据库名
mysql_msg = [['本地mysql', 'localhost', 3306 , 'root', 'abc123', 'zqs'],
['远程mysql', '10.31.1.123', 3306, 'root', 'abc123', 'test']
]
mysql_test3.py
import pymysql, datetime
import csv
import db_setting
import math
from numpy import nan as NaN
class mysql_class(object):
"""对mysql的操作创建一个类"""
def __init__(self, name):
self.name = name
def login_mysql(self):
"""获取mysql的登陆信息"""
mysql_msg = db_setting.mysql_msg
name = self.name
for i in range(0,len(mysql_msg) ):
exec_db = mysql_msg[i]
if name == exec_db[0]:
# 根据输入连接数据库
return exec_db
# conn = pymysql.connect(host=exec_db[1], port=exec_db[2], user=exec_db[3], passwd=exec_db[4],db=exec_db[5])
else:
pass
def csv_insert_mysql(self):
"""将csv的文件录入到mysql"""
exec_db = mysql_class.login_mysql(self)
conn = pymysql.connect(host=exec_db[1], port=exec_db[2], user=exec_db[3], passwd=exec_db[4], db=exec_db[5] ,charset='utf8')
cursor = conn.cursor()
# 测试了数值类型还是会存在问题, yyyy/mm/dd 这类时间格式测试了也不会有问题的
# 数值型空值,必须是 %s 而不能使用 '%s'
# 字符型空值以及时间类型空值,必须是 %s 而不能使用 '%s',但是录入其它非空的字符,又必须用'%s'
sql = ""
sql1 = "insert into emp_csv(empno, ename, job, mgr, hiredate, sal, comm, deptno) values ('%s', %s, '%s', %s, '%s', '%s', %s, '%s') "
sql2 = "insert into emp_csv(empno, ename, job, mgr, hiredate, sal, comm, deptno) values ('%s', '%s', '%s', %s, '%s', '%s', %s, '%s') "
sql3 = "insert into emp_csv(empno, ename, job, mgr, hiredate, sal, comm, deptno) values ('%s', '%s', '%s', %s, %s, '%s', %s, '%s') "
filename = 'E:/python/file_test/emp_csv_2.csv'
with open(filename, 'r') as f:
reader = csv.reader(f)
# print(type(reader))
for i, row in enumerate(reader):
# 剔除第一行的列头
if i > 0:
empno = row[0]
if row[1]:
ename = row[1]
else:
ename = 'NULL'
job = row[2]
if row[3]:
mgr = row[3]
else:
mgr = 'NULL'
if row[4]:
hiredate = row[4]
else:
hiredate = 'NULL'
sal = row[5]
if row[6]:
comm = row[6]
else:
comm = 'NULL'
deptno = row[7]
print(empno, ename, job, mgr , hiredate, sal, comm , deptno)
# 遍历列表,循环录入数据
if not row[1]:
sql = sql1
if not row[4]:
sql = sql3
# 如果存在两列同时为null的情况,还得继续增加判断条件
if row[1]:
if row[4]:
sql = sql2
cursor.execute(sql % (empno, ename, job, mgr, hiredate, sal, comm, deptno))
conn.commit()
# 关闭连接
cursor.close()
conn.close()
if __name__ == '__main__':
my_class1 = mysql_class('本地mysql')
my_class1.csv_insert_mysql()
3.3 通过pymysql将本地mysql数据迁移到远程mysql
其实原理很简单,先在源端mysql将数据存储在列表中,然后再到目标mysql进行insert操作,需要注意的是空值的处理
代码:
db_setting.py
# 存储数据库信息
# 创建一个列表嵌套列表,存储数据库信息
# 依次是 数据库备注、ip、端口、、用户名、密码、登陆数据库名
mysql_msg = [['本地mysql', 'localhost', 3306 , 'root', 'abc123', 'zqs'],
['远程mysql', '10.31.1.123', 3306, 'root', 'abc123', 'test']
]
mysql_test4.py
import pymysql, datetime
import csv
import db_setting
import math
from numpy import nan as NaN
def login_mysql(mysql_name):
"""获取mysql的登陆信息"""
mysql_msg = db_setting.mysql_msg
name = mysql_name
for i in range(0,len(mysql_msg) ):
exec_db = mysql_msg[i]
if name == exec_db[0]:
# 根据输入连接数据库
return exec_db
# conn = pymysql.connect(host=exec_db[1], port=exec_db[2], user=exec_db[3], passwd=exec_db[4],db=exec_db[5])
else:
pass
def t_data():
"""将本地数据库数据同步到远程数据库"""
exec_db = login_mysql('本地mysql')
conn = pymysql.connect(host=exec_db[1], port=exec_db[2], user=exec_db[3], passwd=exec_db[4], db=exec_db[5],charset='utf8')
cursor = conn.cursor()
mysql_result1 = [];
sql1 = "select empno, ename, job, mgr, hiredate, sal, comm, deptno from emp"
cursor.execute(sql1)
for row in cursor.fetchall():
mysql_result1.append(row)
# print(mysql_result1)
# 关闭连接
cursor.close()
conn.close()
# 开始连接目标mysql服务器
exec_db = login_mysql('远程mysql')
conn = pymysql.connect(host=exec_db[1], port=exec_db[2], user=exec_db[3], passwd=exec_db[4], db=exec_db[5],charset='utf8')
cursor = conn.cursor()
sql2 = "insert into emp(empno, ename, job, mgr, hiredate, sal, comm, deptno) values ('%s', '%s', '%s', %s, '%s', '%s', %s, '%s')"
for row in mysql_result1:
# 数值型的null值,中转后变为None,执行insert的时候,默认是会是0 或 0.00 ,这个地方必须中转一下
if row[3]:
mgr = row[3]
else:
mgr = 'NULL'
if row[6]:
comm = row[6]
else:
comm = 'NULL'
cursor.execute(sql2 % (row[0],row[1],row[2],mgr,row[4],row[5],comm,row[7]))
# print(row)
conn.commit()
# 关闭连接
cursor.close()
conn.close()
if __name__ == '__main__':
t_data()