Pandas直接读取sql脚本的方法


Posted in Python onJanuary 21, 2021

之前有群友反应同事给了他一个几百MB的sql脚本,导入数据库再从数据库读取数据有点慢,想了解下有没有可以直接读取sql脚本到pandas的方法。

解析sql脚本文本文件替换成csv格式并加载

我考虑了一下sql脚本也就只是一个文本文件而已,而且只有几百MB,现代的机器足以把它一次性全部加载到内存中,使用python来处理也不会太慢。

我简单研究了一下sql脚本的导出格式,并根据格式写出了以下sql脚本的读取方法。

注意:该读取方法只针对SQLyog导出的mysql脚本测试,其他数据库可能代码需要根据实际情况微调。

读取方法:

from io import StringIO
import pandas as pd
import re

def read_sql_script_all(sql_file_path, quotechar="'") -> (str, dict):
  insert_check = re.compile(r"insert +into +`?(\w+?)`?\(", re.I | re.A)
  with open(sql_file_path, encoding="utf-8") as f:
    sql_txt = f.read()
  end_pos = -1
  df_dict = {}
  while True:
    match_obj = insert_check.search(sql_txt, end_pos+1)
    if not match_obj:
      break
    table_name = match_obj.group(1)
    start_pos = match_obj.span()[1]+1
    end_pos = sql_txt.find(";", start_pos)
    tmp = re.sub(r"\)( values |,)\(", "\n", sql_txt[start_pos:end_pos])
    tmp = re.sub(r"[`()]", "", tmp)
    df = pd.read_csv(StringIO(tmp), quotechar=quotechar)
    dfs = df_dict.setdefault(table_name, [])
    dfs.append(df)
  for table_name, dfs in df_dict.items():
    df_dict[table_name] = pd.concat(dfs)
  return df_dict

参数:

  • sql_file_path:sql脚本的位置
  • quotechar:脚本中字符串是单引号还是双引号,默认使用单引号解析

返回:

一个字典,键是表名,值是该表对应的数据所组成的datafream对象

下面我测试读取下面这个sql脚本:

Pandas直接读取sql脚本的方法

其中的表名是index_test

df_dict = read_sql_script_all("D:/tmp/test.sql")
df = df_dict['index_test']
df.head(10)

结果:

Pandas直接读取sql脚本的方法

可以看到能顺利的直接从sql脚本中读取数据生成datafream。

当然上面写的方法是一次性读取整个sql脚本的所有表,结果为一个字典(键为表名,值为datafream)。但大部分时候我们只需要读取sql脚本的某一张表,我们可以改造一下上面的方法:

def read_sql_script_by_tablename(sql_file_path, table_name, quotechar="'") -> (str, dict):
  insert_check = re.compile(r"insert +into +`?(\w+?)`?\(", re.I | re.A)
  with open(sql_file_path, encoding="utf-8") as f:
    sql_txt = f.read()
  end_pos = -1
  dfs = []
  while True:
    match_obj = insert_check.search(sql_txt, end_pos+1)
    if not match_obj:
      break
    start_pos = match_obj.span()[1]+1
    end_pos = sql_txt.find(";", start_pos)
    if table_name != match_obj.group(1):
      continue
    tmp = re.sub(r"\)( values |,)\(", "\n", sql_txt[start_pos:end_pos])
    tmp = re.sub(r"[`()]", "", tmp)
    df = pd.read_csv(StringIO(tmp), quotechar=quotechar)
    dfs.append(df)
  return pd.concat(dfs)

参数:

  • sql_file_path:sql脚本的位置
  • table_name:被读取的表名
  • quotechar:脚本中字符串是单引号还是双引号,默认使用单引号解析

返回:

该表所对应的datafream对象

读取代码:

df = read_sql_script_by_tablename("D:/tmp/test.sql", "index_test")
df.head()

结果:

Pandas直接读取sql脚本的方法

将sql脚本转换为sqlite格式并通过本地sql连接读取

在写完上面的方法后,我又想到另一种解决思路,就是将sql脚本转换成sqlite语法的sql语句,然后直接加载。各种类型的数据库的sql语句变化较大,下面的方法仅针对SQLyog导出的mysql脚本测试通过,如果是其他的数据库,可能下面的方法仍然需要微调。最好是先自行将sql脚本转换为sqlite语法的sql语句后,再使用我写的方法加载。

加载sql脚本的方法:

from sqlalchemy import create_engine
import pandas as pd
import re


def load_sql2sqlite_conn(sqltxt_path):
  create_rule = re.compile("create +table [^;]+;", re.I)
  insert_rule = re.compile("insert +into [^;]+;", re.I)
  with open(sqltxt_path, encoding="utf-8") as f:
    sqltxt = f.read()
  engine = create_engine('sqlite:///:memory:')
  pos = -1
  while True:
    match_obj = create_rule.search(sqltxt, pos+1)
    if match_obj:
      pos = match_obj.span()[1]
      sql = match_obj.group(0).replace("AUTO_INCREMENT", "")
      sql = re.sub("\).+;", ");", sql)
      engine.execute(sql)
    match_obj = insert_rule.search(sqltxt, pos+1)
    if match_obj:
      pos = match_obj.span()[1]
      sql = match_obj.group(0)
      engine.execute(sql)
    else:
      break
  tablenames = [t[0] for t in engine.execute(
    "SELECT tbl_name FROM sqlite_master WHERE type='table';").fetchall()]
  return tablenames, engine.connect()

参数:

sql_file_path:sql脚本的位置

返回:

两个元素的元组,第一个元素是表名列表,第二个元素是sqlite内存虚拟连接

测试读取:

tablenames, conn = load_sql2sqlite_conn("D:/tmp/test.sql")
tablename = tablenames[0]
print(tablename)
df = pd.read_sql(f"select * from {tablename};", conn)
df

结果:

Pandas直接读取sql脚本的方法

到此这篇关于Pandas直接读取sql脚本的文章就介绍到这了,更多相关Pandas读取sql脚本内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Python 相关文章推荐
用实例说明python的*args和**kwargs用法
Nov 01 Python
django通过ajax发起请求返回JSON格式数据的方法
Jun 04 Python
Django查找网站项目根目录和对正则表达式的支持
Jul 15 Python
python实现备份目录的方法
Aug 03 Python
Python2和Python3.6环境解决共存问题
Nov 09 Python
Python 多个图同时在不同窗口显示的实现方法
Jul 07 Python
pytorch forward两个参数实例
Jan 17 Python
Python 自由定制表格的实现示例
Mar 20 Python
解决jupyter notebook打不开无反应 浏览器未启动的问题
Apr 10 Python
python实现飞船游戏的纵向移动
Apr 24 Python
Python通过len函数返回对象长度
Oct 22 Python
pytorch下的unsqueeze和squeeze的用法说明
Feb 06 Python
python asyncio 协程库的使用
Jan 21 #Python
python palywright库基本使用
Jan 21 #Python
python Scrapy爬虫框架的使用
Jan 21 #Python
python 可视化库PyG2Plot的使用
Jan 21 #Python
详解基于Facecognition+Opencv快速搭建人脸识别及跟踪应用
Jan 21 #Python
Python实现石头剪刀布游戏
Jan 20 #Python
python程序实现BTC(比特币)挖矿的完整代码
Jan 20 #Python
You might like
PHP 模板高级篇总结
2006/12/21 PHP
PHP Warning: PHP Startup: Unable to load dynamic library \ D:/php5/ext/php_mysqli.dll\
2012/06/17 PHP
laravel中数据显示方法(默认值和下拉option默认选中)
2019/10/11 PHP
jQuery初学:find()方法及children方法的区别分析
2011/01/31 Javascript
juqery 学习之五 文档处理 插入
2011/02/11 Javascript
基于jQuery的动态表格插件
2011/03/28 Javascript
JavaScript图片轮播代码分享
2015/07/31 Javascript
jquery京东商城双11焦点图多图广告特效代码分享
2015/09/06 Javascript
基于JavaScript实现通用tab选项卡(通用性强)
2016/01/07 Javascript
ionic开发中点击input时键盘自动弹出
2016/12/23 Javascript
Ajax异步文件上传与NodeJS express服务端处理
2017/04/01 NodeJs
vue2.0+ 从插件开发到npm发布的示例代码
2018/04/28 Javascript
实例介绍JavaScript中多种组合继承
2019/01/20 Javascript
JavaScript数组去重的方法总结【12种方法,号称史上最全】
2019/02/28 Javascript
vue iview的菜单组件Mune 点击不高亮的解决方案
2019/11/01 Javascript
[52:20]DOTA2-DPC中国联赛正赛 SAG vs XGBO3 第一场 3月5日
2021/03/11 DOTA
Python数据类型学习笔记
2016/01/13 Python
python win32 简单操作方法
2017/05/25 Python
获取python文件扩展名和文件名方法
2018/02/02 Python
python去除扩展名的实例讲解
2018/04/23 Python
在python中创建指定大小的多维数组方式
2019/11/28 Python
Python导入数值型Excel数据并生成矩阵操作
2020/06/09 Python
如何用Matplotlib 画三维图的示例代码
2020/07/28 Python
美国标志性加大尺码时装品牌:Ashley Stewart
2016/12/15 全球购物
Mio Skincare法国官网:身体紧致及孕期身体护理
2018/04/04 全球购物
美国嘻哈文化生活方式品牌:GLD
2018/04/15 全球购物
琳达·法罗眼镜英国官网:Linda Farrow英国
2021/01/19 全球购物
外国语学院毕业生自荐信
2013/10/28 职场文书
投标担保书范文
2014/04/02 职场文书
学校校庆演讲稿
2014/05/22 职场文书
领导班子对照检查剖析材料
2014/10/13 职场文书
入党宣誓仪式主持词
2015/06/29 职场文书
朋友聚会祝酒词
2015/08/10 职场文书
2019最新公司租房合同(例文)
2019/07/18 职场文书
mysql 索引合并的使用
2021/08/30 MySQL
JavaScript模拟实现网易云轮播效果
2022/04/04 Javascript