问题:
dataframe写入数据库的时候,columns与sql字段不一致,怎么按照columns对应写入?
背景:
工作中遇到的问题,实现Python脚本自动读取excel文件并写入数据库,操作时候发现,系统下载的Excel文件并不是一直固定的,基本上过段时间就会调整次,原始to_sql方法只能整体写入,当字段无法对齐columns时,会造成数据的混乱,由于本人自学Python,也经常在csdn上找答案,这个问题找了两天,并未找到类似解决办法,基本上都是基础的to_sql,再经过灵光乍现后,自己研究出来实现方法,特放出来交流学习。
思路:
在python中
sql=“xxxxxxxx”
cursor.execute(sql)
execute提交的是 个字符串,所以考虑格式化字符串传参
insert into (%s,%s,%s,%s、、、、)values(%s,%s,%s、、、)
这样的结果就是当字段特别大的时候能累死,而且我又很懒
最重要的是当换个数据库的时候又废了
sql="insert into (%s,%s,%s,%s、、、、)values(%s,%s,%s、、、)"
都在引号里面,n个 %s 和一个 %s 也没什么区别吧!!!
所以我就想着把整个字段名和逗号一起拼接成一个字符串
实例:
import pymysql
import pandas as pd
import numpy as np
# 定义函数
def w_sql(sql_name,data,zd):
connent = pymysql.connect(host='xxx', user='xxx', passwd='xxxx', db='xxxx', charset='xxx') #连接数据库
cursor = connent.cursor()#创建游标
for i in data.values:
va=""
for j in i:
if pd.isnull(j):
va=va+","+'null' #缺失值判断和转换
else:
va=va+","+"'"+str(j)+"'"
sql="""insert ignore into %s (%s) values(%s)"""%(sql_name,zd[:-1],va[1:])
# print(sql)
cursor.execute(sql)
connent.commit() #提交事务
cursor.close()#关闭游标
connent.close()#断开连接
#主程序
data=pd.read_excel("./test.xlsx")
sql_name='test'
zd=""
for j in data.columns:
zd=zd+j+","
w_sql(sql_name,data,zd)
结果如下图,字段始终对齐,不受位置干扰,
【注意】
①ignore 是忽略主键重复,
最开始的版本是不设置主键,选取dataframe第一个元素在 数据库里进行select,
版本二 发现第一个元素不准,所以又read_sql_table读取整个数据库,对dataframe 进行布尔筛选
…
最终拼接了个主键,用ignore忽略重复——注意去除警告,否则多次运行就会一片红红火火
这里给出警告过滤的代码
# 警告过滤
# 可以通过调用filterwarnings()将规则添加到过滤器
# 并通过调用resetwarnings()将其重置为默认状态
# warnings.filterwarnings("ignore")
②因为是拼接的字符串所以数据库对应要设置为char/varchar
③commit的缩进位置
因为是dataframe一行行执行写入,最后循环完一整个dataframe统一commit
当数据量大的时候commit的位置很影响效率
connent.commit() #提交事务