使用Python实现将多表分批次从数据库导出到Excel


Posted in Python onMay 15, 2020

一、应用场景

为了避免反复的手手工从后台数据库导出某些数据表到Excel文件、高效率到多份离线数据。

二、功能事项

支持一次性导出多个数据源表、自动获取各表的字段名。

支持控制批次的写入速率。例如:每5000行一个批次写入到excel。

支持结构相同的表导入到同一个Excel文件。可适用于经过水平切分后的分布式表。

三、主要实现

1、概览

A[创建类] -->|方法1| B(创建数据库连接)
A[创建类] -->|方法2| C(取查询结果集)
A[创建类] -->|方法3| D(利用句柄写入Excel)
A[创建类] -->|方法4| E(读取多个源表)

B(创建数据库连接) -->U(调用示例)
C(取查询结果集) -->U(调用示例)
D(利用句柄写入Excel) -->U(调用示例)
E(读取多个源表) -->U(调用示例)

2、主要方法

首先需要安装第三方库pymssql实现对SQLServer的连接访问,自定义方法__getConn()需要指定如下五个参数:服务器host、登录用户名user、登录密码pwd、指定的数据库db、字符编码charset。连接成功后,通过cursor()获取游标对象,它将用来执行数据库脚本,并得到返回结果集和数据总量。

创建数据库连接和执行SQL的源码:

def __init__(self,host,user,pwd,db):
    self.host = host
    self.user = user
    self.pwd = pwd
    self.db = db

  def __getConn(self):
    if not self.db:
      raise(NameError,'没有设置数据库信息')
    self.conn = pymssql.connect(host=self.host, user=self.user, password=self.pwd, database=self.db, charset='utf8')
    cur = self.conn.cursor()
    if not cur:
      raise(NameError,'连接数据库失败')
    else:
      return cur

3、方法3中写入Excel时,注意一定要用到Pandas中的公共句柄ExcelWriter对象writer。当数据被分批多次写入同一个文件时,如果直接使用to_excel()方法,则前面批次的结果集将会被后续结果覆盖。增加了这个公共句柄限制后,后面的写入会累加到前面写入的数据尾部行,而不是全部覆盖。

writer = pd.ExcelWriter(file)
df_fetch_data[rs_startrow:i*N].to_excel(writer, header=isHeader, index=False, startrow=startRow)

分批次写入到目标Excel时的另一个要注意的参数是写入行startrow的设置。每次写入完成后需要重新指下一批次数据的初始位置值。每个批次的数据会记录各自的所属批次信息。

利用关键字参数**args 指定多个数据源表和数据库连接。

def exportToExcel(self, **args):
  for sourceTB in args['sourceTB']:    
    arc_dict = dict(
      sourceTB = sourceTB,
      path=args['path'],
      startRow=args['startRow'],
      isHeader=args['isHeader'],
      batch=args['batch']
    )
    print('\n当前导出的数据表为:%s' %(sourceTB))
    self.writeToExcel(**arc_dict)
  return 'success'

四、先用类MSSQL创建对象,再定义关键字参数args,最终调用方法导出到文件即完成数据导出。

#!/usr/bin/env python
# coding: utf-8

# 主要功能:分批次导出大数据量、结构相同的数据表到excel 
# 导出多个表的数据到各自的文件, 
# 目前问题:to_excel 虽然设置了分批写入,但先前的数据会被下一次写入覆盖,
# 利用Pandas包中的ExcelWriter()方法增加一个公共句柄,在写入新的数据之时保留原来写入的数据,等到把所有的数据都写进去之后关闭这个句柄
import pymssql 
import pandas as pd 
import datetime 
import math
 
class MSSQL(object):
  def __init__(self,host,user,pwd,db):
    self.host = host
    self.user = user
    self.pwd = pwd
    self.db = db
 
  def __getConn(self):
    if not self.db:
      raise(NameError,'没有设置数据库信息')
    self.conn = pymssql.connect(host=self.host, user=self.user, password=self.pwd, database=self.db, charset='utf8')
    cur = self.conn.cursor()
    if not cur:
      raise(NameError,'连接数据库失败')
    else:
      return cur
   
  def executeQuery(self,sql):
    cur = self.__getConn()
    cur.execute(sql)
    # 获取所有数据集
    # fetchall()获取结果集中的剩下的所有行
    # 如果数据量太大,是否需要分批插入 
    resList, rowcount = cur.fetchall(),cur.rowcount
    self.conn.close()
    return (resList, rowcount)
 
  # 导出单个数据表到excel 
  def writeToExcel(self,**args):
    sourceTB = args['sourceTB']
    columns = args.get('columns')
    path=args['path']
    fname=args.get('fname')
    startRow=args['startRow']
    isHeader=args['isHeader']
    N=args['batch']
     
    # 获取指定源数据列
    if columns is None:
      columns_select = ' * '
    else:
      columns_select = ','.join(columns)
     
    if fname is None:
      fname=sourceTB+'_exportData.xlsx'
     
    file = path + fname
    # 增加一个公共句柄,写入新数据时,保留原数据 
    writer = pd.ExcelWriter(file)
     
    sql_select = 'select '+ columns_select + ' from '+ sourceTB
    fetch_data, rowcount = self.executeQuery(sql_select)
    # print(rowcount)
     
    df_fetch_data = pd.DataFrame(fetch_data)
    # 一共有roucount行数据,每N行一个batch提交写入到excel 
    times = math.floor(rowcount/N)
    i = 1
    rs_startrow = 0
    # 当总数据量 > 每批插入的数据量时 
    print(i, times)
    is_while=0
    while i <= times:
      is_while = 1
      # 如果是首次,且指定输入标题,则有标题
      if i==1:
        # isHeader = True
        startRow = 1
      else:
        # isHeader = False
        startRow+=N
      # 切片取指定的每个批次的数据行 ,前闭后开 
      # startrow: 写入到目标文件的起始行。0表示第1行,1表示第2行。。。
      df_fetch_data['batch'] = 'batch'+str(i)
      df_fetch_data[rs_startrow:i*N].to_excel(writer, header=isHeader, index=False, startrow=startRow)
      print('第',str(i),'次循环,取源数据第',rs_startrow,'行至',i*N,'行','写入到第',startRow,'行')
      print('第',str(i),'次写入数据为:',df_fetch_data[rs_startrow:i*N])
      # 重新指定源数据的读取起始行
      rs_startrow =i * N
      i+=1
 
    # 写入文件的开始行数
    # 当没有做任何循环时,仍然从第一行开始写入
    if is_while == 0:
      startRow = startRow
    else:
      startRow+=N
    df_fetch_data['batch'] = 'batch'+str(i)
    print('第{0}次读取数据,从第{1}行开始,写入到第{2}行!'.format(str(i), str(rs_startrow), str(startRow)))
    print('第',str(i),'写入数据为:',df_fetch_data[rs_startrow:i*N])
    df_fetch_data[rs_startrow:i*N].to_excel(writer, header=isHeader, index=False, startrow=startRow)
     
    # 注: 这里一定要saver()将数据从缓存写入磁盘!!!!!!!!!!!!!!!!!!!!!1
    writer.save()
     
    start_time=datetime.datetime.now()
  # 导出结构相同的多个表到同一样excel
  def exportToExcel(self, **args):
    for sourceTB in args['sourceTB']:    
      arc_dict = dict(
        sourceTB = sourceTB,
        path=args['path'],
        startRow=args['startRow'],
        isHeader=args['isHeader'],
        batch=args['batch']
      )
      print('\n当前导出的数据表为:%s' %(sourceTB))
      self.writeToExcel(**arc_dict)
       
    return 'success'
    start_time=datetime.datetime.now()
 
if __name__ == "__main__":
  ms = MSSQL(host="localhost",user="test",pwd="test",db="db_jun")
   
  args = dict(
   sourceTB = ['tb2', 'tb1'],# 待导出的表
   path='D:\\myPC\\Python\\',# 导出到指定路径
   startRow=1,#设定写入文件的首行,第2行为数据首行
   isHeader=False,# 是否包含源数据的标题
   batch=5
  )
  # 导出多个文件
  ms.exportToExcel(**args)

以上这篇使用Python实现将多表分批次从数据库导出到Excel就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python科学计算环境推荐——Anaconda
Jun 30 Python
解决python3中自定义wsgi函数,make_server函数报错的问题
Nov 21 Python
用Python写一段用户登录的程序代码
Apr 22 Python
解决Python3.5+OpenCV3.2读取图像的问题
Dec 05 Python
Django框架模板注入操作示例【变量传递到模板】
Dec 19 Python
python3正则模块re的使用方法详解
Feb 11 Python
Python loguru日志库之高效输出控制台日志和日志记录
Mar 07 Python
使用python实现飞机大战游戏
Mar 23 Python
关于jupyter打开之后不能直接跳转到浏览器的解决方式
Apr 13 Python
python中sklearn的pipeline模块实例详解
May 21 Python
python 实现的截屏工具
May 08 Python
python读取mnist数据集方法案例详解
Sep 04 Python
解决python执行较大excel文件openpyxl慢问题
May 15 #Python
python可迭代对象去重实例
May 15 #Python
python 操作mysql数据中fetchone()和fetchall()方式
May 15 #Python
Python实现UDP程序通信过程图解
May 15 #Python
解决pymysql cursor.fetchall() 获取不到数据的问题
May 15 #Python
python如何解析复杂sql,实现数据库和表的提取的实例剖析
May 15 #Python
pymysql之cur.fetchall() 和cur.fetchone()用法详解
May 15 #Python
You might like
刷新PHP缓冲区为你的站点加速
2015/10/10 PHP
Laravel中Trait的用法实例详解
2016/03/16 PHP
Nginx环境下PHP flush失效的解决方法
2016/10/19 PHP
浅析PHP中的闭包和匿名函数
2017/12/25 PHP
ThinkPHP5.0框架控制器继承基类和自定义类示例
2018/05/25 PHP
php生成二维码不保存服务器还有下载功能的实现代码
2018/08/09 PHP
php实现文章评论系统
2019/02/18 PHP
jQuery设置与获取HTML,文本和值的简单实例
2014/02/26 Javascript
jQuery基于扩展实现的倒计时效果
2016/05/14 Javascript
html+js实现简单的计算器代码(加减乘除)
2016/07/12 Javascript
浅谈js的ajax的异步和同步请求的问题
2016/10/07 Javascript
Vue方法与事件处理器详解
2016/12/01 Javascript
原生js实现打字动画游戏
2017/02/04 Javascript
详解webpack + react + react-router 如何实现懒加载
2017/11/20 Javascript
推荐10款扩展Web表单的JS插件
2017/12/25 Javascript
微信小程序之圆形进度条实现思路
2018/02/22 Javascript
bootstrap table支持高度百分比的实例代码
2018/02/28 Javascript
了解重排与重绘
2019/05/29 Javascript
学习LayUI时自研的表单参数校验框架案例分析
2019/07/29 Javascript
借助云开发实现小程序短信验证码的发送
2020/01/06 Javascript
python实现感知器算法详解
2017/12/19 Python
Python3结合Dlib实现人脸识别和剪切
2018/01/24 Python
在python中只选取列表中某一纵列的方法
2018/11/28 Python
python+mysql实现学生信息查询系统
2019/02/21 Python
python随机生成库faker库api实例详解
2019/11/28 Python
Python PyInstaller安装和使用教程详解
2020/01/08 Python
吉尔德利巧克力公司:Ghirardelli Chocolate Company
2019/03/27 全球购物
后勤副校长自我鉴定
2013/10/13 职场文书
医学院学生求职简历的自我评价
2013/10/24 职场文书
代办委托书怎样写
2014/04/08 职场文书
书香家庭事迹材料
2014/05/09 职场文书
婚庆答谢词
2015/01/04 职场文书
关于远足的感想
2015/08/10 职场文书
先进基层党组织事迹材料2016
2016/02/29 职场文书
通过shell脚本对mysql的增删改查及my.cnf的配置
2021/07/07 MySQL
Java死锁的排查
2022/05/11 Java/Android