使用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时区设置方法与pytz查询时区教程
Nov 27 Python
Python中线程编程之threading模块的使用详解
Jun 23 Python
Python设计模式之抽象工厂模式
Aug 25 Python
Python构建XML树结构的方法示例
Jun 30 Python
pandas.DataFrame 根据条件新建列并赋值的方法
Apr 08 Python
详解pyqt5 动画在QThread线程中无法运行问题
May 05 Python
Python中请不要再用re.compile了
Jun 30 Python
python加载自定义词典实例
Dec 06 Python
keras自定义回调函数查看训练的loss和accuracy方式
May 23 Python
Python 捕获代码中所有异常的方法
Aug 03 Python
python 从list中随机取值的方法
Nov 16 Python
python 闭包函数详细介绍
Apr 19 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/02/11 PHP
基于swoole实现多人聊天室
2018/06/14 PHP
Yii2.0框架模型多表关联查询示例
2019/07/18 PHP
如何在Laravel5.8中正确地应用Repository设计模式
2019/11/26 PHP
JavaScript 学习点滴记录
2009/04/24 Javascript
jquery 简短右键菜单 多浏览器兼容
2010/01/01 Javascript
jQuery 锚点跳转滚动条平滑滚动一句话代码
2010/04/30 Javascript
js获得地址栏?问号后参数的方法
2013/08/08 Javascript
浅析jquery的作用与优势
2013/12/02 Javascript
JS获取各种宽度、高度的简单介绍
2014/12/19 Javascript
JS实现很实用的对联广告代码(可自适应高度)
2015/09/18 Javascript
原生javascript 学习之js变量全面了解
2016/07/14 Javascript
响应式表格之固定表头的简单实现
2016/08/26 Javascript
基于JavaScript实现的希尔排序算法分析
2017/04/14 Javascript
一个简易时钟效果js实现代码
2020/03/25 Javascript
vue.js与element-ui实现菜单树形结构的解决方法
2018/04/21 Javascript
Angular设置别名alias的方法
2018/11/08 Javascript
es6 symbol的实现方法示例
2019/04/02 Javascript
基于Vue CSR的微前端实现方案实践
2020/05/27 Javascript
ant design 日期格式化的实现
2020/10/27 Javascript
JavaScript枚举选择jquery插件代码实例
2020/11/17 jQuery
Python中使用HTMLParser解析html实例
2015/02/08 Python
Python复制文件操作实例详解
2015/11/10 Python
Python编程之string相关操作实例详解
2017/07/22 Python
Python爬虫番外篇之Cookie和Session详解
2017/12/27 Python
Python 爬虫之Beautiful Soup模块使用指南
2018/07/05 Python
Django实现WebSSH操作物理机或虚拟机的方法
2019/11/06 Python
python 画3维轨迹图并进行比较的实例
2019/12/06 Python
在python中做正态性检验示例
2019/12/09 Python
python opencv进行图像拼接
2020/03/27 Python
Python extract及contains方法代码实例
2020/09/11 Python
使用css3做0.5px的细线的示例代码
2018/01/18 HTML / CSS
澳大利亚设计师服装在线:MISHA
2019/10/07 全球购物
11月红领巾广播稿
2014/01/17 职场文书
幼儿园美术教学反思
2014/01/31 职场文书
食品卫生管理制度
2015/08/06 职场文书