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连接mysql数据库示例(做增删改操作)
Dec 31 Python
python matplotlib 在指定的两个点之间连线方法
May 25 Python
深入浅析Python的类
Jun 22 Python
ubuntu16.04制作vim和python3的开发环境
Sep 23 Python
python自动发邮件总结及实例说明【推荐】
May 31 Python
pyqt 多窗口之间的相互调用方法
Jun 19 Python
django多种支付、并发订单处理实例代码
Dec 13 Python
python通过安装itchat包实现微信自动回复收到的春节祝福
Jan 19 Python
Python常见反爬虫机制解决方案
Jun 01 Python
python写文件时覆盖原来的实例方法
Jul 22 Python
python中常用的数据结构介绍
Jan 12 Python
Python合并多张图片成PDF
Jun 09 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 异常处理实现代码
2009/03/10 PHP
PHP利用func_get_args和func_num_args函数实现函数重载实例
2014/11/12 PHP
PHP SPL标准库中的常用函数介绍
2015/05/11 PHP
PHP实现上传文件并存进数据库的方法
2015/07/16 PHP
PHPMailer使用QQ邮箱实现邮件发送功能
2017/08/18 PHP
CodeIgniter整合Smarty的方法详解
2017/08/25 PHP
window.addeventjs事件驱动函数集合addEvent等
2008/02/19 Javascript
yepnope.js 异步加载资源文件
2011/09/08 Javascript
JS代码放在head和body中的区别分析
2011/12/01 Javascript
兼容ie、firefox的图片自动缩放的css跟js代码分享
2013/08/12 Javascript
JS Date函数整理方便使用
2013/10/23 Javascript
将数字转换成大写的人民币表达式的js函数
2014/09/21 Javascript
jQuery简单实现tab选项卡切换效果
2016/06/20 Javascript
jquery+ajax+text文本框实现智能提示完整实例
2016/07/09 Javascript
js 判断各种数据类型的简单方法(推荐)
2016/08/29 Javascript
vue2.0获取自定义属性的值
2017/03/28 Javascript
jq checkbox 的全选并ajax传参的实例
2017/04/01 Javascript
JS使用Dijkstra算法求解最短路径
2019/01/17 Javascript
微信小程序如何获取用户头像和昵称
2019/09/23 Javascript
Python编程中装饰器的使用示例解析
2016/06/20 Python
python实现自动网页截图并裁剪图片
2018/07/30 Python
Python Scapy随心所欲研究TCP协议栈
2018/11/20 Python
Python编程学习之如何判断3个数的大小
2019/08/07 Python
torchxrayvision包安装过程(附pytorch1.6cpu版安装)
2020/08/26 Python
聊聊python在linux下与windows下导入模块的区别说明
2021/03/03 Python
阿根廷旅游网站:almundo阿根廷
2018/02/12 全球购物
你所在的项目是如何确定版本号的
2015/12/28 面试题
中秋节礼品促销方案
2014/02/02 职场文书
考试违纪检讨书
2014/02/02 职场文书
毕业生求职自荐书范文
2014/03/27 职场文书
艾滋病宣传活动总结
2014/05/08 职场文书
煤矿安全协议书
2014/08/20 职场文书
文明社区申报材料
2014/08/21 职场文书
观看《杨善洲》宣传教育片心得体会
2016/01/23 职场文书
NoSQL优缺点与MongoDB数据库简介
2022/06/05 MongoDB
vue递归实现树形组件
2022/07/15 Vue.js