网上关于python操作db2的文章很少,特此记录。
环境
- Python 3.8.6
- ibm_db_sa 0.3.7
- ibm-db 3.0.4
- sqlalchemy 1.4.7
1. 最终解决方案
采用拼接字符串的方法,把要批量插入的数据拼接成insert into table values (),...,(),()
这种形式。
def save_batch_db2(self, ssql, df):
""" 向db2数据库中批量导入数据
:param df:DataFrame
:param ssql:提供拼接的sql的前半部分 e.g. insert into table values
"""
tuplesValues = [tuple(x) for x in df.values]
# 此时的sqlStr: [('colunm1','colunm1','colunm1'),(...),(...)]
sqlStr = str(tuplesValues)
# 截取
sqlStr = sqlStr[1:len(sqlStr) - 1]
#拼接并执行
sql3 = ssql + sqlStr
self.db_gp_connect.insert(sql3)
用时3.5秒左右,未截图。
由于之前未接触过python,加之python处理db2网络上教程很少。探索的过程中也出现了各式各样的bug。
2. 探索1:load & import
我一开始的思路是先将数据导入csv文件中,然后再将csv文件转储到db2中,再通过python脚本调用命令行执行csv导入db2的命令。通过百度得知load
和import
可以完成这个工作。前者比后者效率更高。代码我也写出来了,如下
LOAD client FROM filePath/xxx.csv of del INSERT INTO tableName
IMPORT from filePath/xxx.csv of del INSERT INTO tableName
但是这个行不通,原因如下:
- python写脚本调用db2命令行我没写过,不擅长,学习成本过高。
- 运行程序的服务器上没安装db2,无法运行db2命令行。
- 数据库和程序在不同服务器上,不晓得这个命令能不能用。
3. 探索2:to_sql
这个最终实现了,代码如下:
import sqlalchemy
from sqlalchemy import *
import ibm_db
import ibm_db_sa
def func(self,param1,...):
engine = create_engine("db2+ibm_db://user:pass@host:50000/database")
df.to_sql(name='tableName', chunksize=1000, con=engine, if_exists='append', index=False)
插入大约5400条数据用时: 7.996s
4. 探索3: excutemany(sql,param)
param是需要批量插入的数据,形式为列表或者元组。通过读源码得知这个内部其实也是调用的excute一条一条插入数据,效率比前面的方法差距太大。这个也实现了,代码简单就不贴了。(其实是代码忘记保存了,懒得重写了,哈哈哈)
5. 遇到的bug
SQLCODE=-803
通过查询得知是主键冲突。检查sql,发现是读取数据的时候误操作导致的,修改后程序正常运行。
写这篇博客的时候,我是非常开心的,因为解决了一个困扰我很久的bug,解决了批量插入db2数据库这一技术问题。排查主键重复这个bug的时候写出来很轻松。实际上花了不少时间。由于粗心边界值判断多一个‘=’导致分数为60分的数据出现两行。
由此得出两点结论:
1.写代码要细心
2.认识是螺旋上升的,不要气馁
凡事多问自己一句:不试试怎么知道呢?