使用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中的try和finally和with方法
May 05 Python
Python松散正则表达式用法分析
Apr 29 Python
详解Python中的__new__、__init__、__call__三个特殊方法
Jun 02 Python
Python+Pika+RabbitMQ环境部署及实现工作队列的实例教程
Jun 29 Python
windows下Python实现将pdf文件转化为png格式图片的方法
Jul 21 Python
Python字典的核心底层原理讲解
Jan 24 Python
python matplotlib画图库学习绘制常用的图
Mar 19 Python
使用Python检测文章抄袭及去重算法原理解析
Jun 14 Python
pytorch 数据处理:定义自己的数据集合实例
Dec 31 Python
使用keras根据层名称来初始化网络
May 21 Python
Python非单向递归函数如何返回全部结果
Dec 18 Python
Python操作Excel的学习笔记
Feb 18 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购物车实现代码
2011/10/10 PHP
php中使用DOM类读取XML文件的实现代码
2011/12/14 PHP
php不使用插件导出excel的简单方法
2014/03/04 PHP
php实现的验证码文件类实例
2015/06/18 PHP
php在windows环境下获得cpu内存实时使用率(推荐)
2018/02/08 PHP
PHP中单例模式的使用场景与使用方法讲解
2019/03/18 PHP
List the UTC Time on a Computer
2007/06/11 Javascript
javascript qq右下角滑出窗口 sheyMsg
2010/03/21 Javascript
$.ajax返回的JSON无法执行success的解决方法
2011/09/09 Javascript
JS学习之表格的排序简单实例
2016/05/16 Javascript
livereload工具实现前端可视化开发【推荐】
2016/12/23 Javascript
js中的DOM模拟购物车功能
2017/03/22 Javascript
Javascript中click与blur事件的顺序详析
2017/04/25 Javascript
BootStrap模态框不垂直居中的解决方法
2017/10/19 Javascript
详解使用 Node.js 开发简单的脚手架工具
2018/06/08 Javascript
微信小程序支付PHP代码
2018/08/23 Javascript
JavaScript数组去重的方法总结【12种方法,号称史上最全】
2019/02/28 Javascript
Javascript Dom元素获取和添加详解
2019/09/24 Javascript
原生js拖拽实现图形伸缩效果
2020/02/10 Javascript
jquery实现异步文件上传ajaxfileupload.js
2020/10/23 jQuery
Python编写屏幕截图程序方法
2015/02/18 Python
python与sqlite3实现解密chrome cookie实例代码
2018/01/20 Python
Python代码缩进和测试模块示例详解
2018/05/07 Python
pyqt5 键盘监听按下enter 就登陆的实例
2019/06/25 Python
python脚本监控logstash进程并邮件告警实例
2020/04/28 Python
详解HTML5中的拖放事件(Drag 和 drop)
2016/11/14 HTML / CSS
在weblogic中发布ejb需涉及到哪些配置文件
2012/01/17 面试题
实习老师个人总结的自我评价
2013/09/28 职场文书
微博营销计划书
2014/01/10 职场文书
员工安全责任书范本
2014/07/24 职场文书
后勤管理员岗位职责
2014/08/27 职场文书
婚前协议书标准版
2014/10/19 职场文书
文明单位申报材料
2014/12/23 职场文书
商超业务员岗位职责
2015/02/13 职场文书
朋友聚会祝酒词
2015/08/10 职场文书
Python3中PyQt5简单实现文件打开及保存
2021/06/10 Python