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 相关文章推荐
pyramid配置session的方法教程
Nov 27 Python
python在linux中输出带颜色的文字的方法
Jun 19 Python
python Django批量导入数据
Mar 25 Python
python爬虫爬取快手视频多线程下载功能
Feb 28 Python
Python实现的端口扫描功能示例
Apr 08 Python
解决python文件双击运行秒退的问题
Jun 24 Python
django的model操作汇整详解
Jul 26 Python
在macOS上搭建python环境的实现方法
Aug 13 Python
python实现字典嵌套列表取值
Dec 16 Python
TensorFlow:将ckpt文件固化成pb文件教程
Feb 11 Python
解决IDEA 的 plugins 搜不到任何的插件问题
May 04 Python
keras实现theano和tensorflow训练的模型相互转换
Jun 19 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类中的各种拦截器用法分析
2014/11/03 PHP
php通过sort()函数给数组排序的方法
2015/03/18 PHP
php 输入输出流详解及示例代码
2016/08/25 PHP
thinkPHP自动验证、自动添加及表单错误问题分析
2016/10/17 PHP
PHP会话控制实例分析
2016/12/24 PHP
PHP哈希表实现算法原理解析
2020/12/11 PHP
淘宝搜索框效果实现分析
2011/03/05 Javascript
jquery ztree实现下拉树形框使用到了json数据
2014/05/14 Javascript
js实现百度联盟中一款不错的图片切换效果完整实例
2015/03/04 Javascript
数据分析软件之FineReport教程:[5]参数界面JS(全)
2015/08/13 Javascript
字太多用...代替的方法(两种)
2017/03/15 Javascript
jQuery实现的文字逐行向上间歇滚动效果示例
2017/09/06 jQuery
JavaScript伪数组用法实例分析
2017/12/22 Javascript
vue、react等单页面项目应该这样子部署到服务器
2018/01/03 Javascript
详解开发react应用最好用的脚手架 create-react-app
2018/04/24 Javascript
解决vue跨域axios异步通信问题
2019/04/17 Javascript
JS时间戳与日期格式互相转换的简单方法示例
2021/01/30 Javascript
JavaScript实现HTML导航栏下拉菜单
2020/11/25 Javascript
python 中random模块的常用方法总结
2017/07/08 Python
python 除法保留两位小数点的方法
2018/07/16 Python
python重试装饰器的简单实现方法
2019/01/31 Python
Django+zTree构建组织架构树的方法
2019/08/21 Python
python 实现一个反向单位矩阵示例
2019/11/29 Python
浅谈keras 模型用于预测时的注意事项
2020/06/27 Python
Keras预训练的ImageNet模型实现分类操作
2020/07/07 Python
CSS3区域模块region相关编写示例
2015/08/28 HTML / CSS
澳大利亚领先的内衣店:Bendon Lingerie澳大利亚
2020/05/15 全球购物
俄罗斯购买自行车网站:Vamvelosiped
2021/01/29 全球购物
企业管理培训感言
2014/01/27 职场文书
创业计划实施的7大步骤
2014/02/05 职场文书
信息技术毕业生自荐信范文
2014/03/13 职场文书
电大奖学金获奖感言
2014/08/14 职场文书
送达通知书
2015/04/25 职场文书
西游降魔篇观后感
2015/06/15 职场文书
钢铁是怎样炼成的读书笔记
2015/06/29 职场文书
总结python多进程multiprocessing的相关知识
2021/06/29 Python