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中条件选择和循环语句使用方法介绍
Mar 13 Python
python使用WMI检测windows系统信息、硬盘信息、网卡信息的方法
May 15 Python
python实现图片变亮或者变暗的方法
Jun 01 Python
Python中函数的参数定义和可变参数用法实例分析
Jun 04 Python
Python写的一个简单监控系统
Jun 19 Python
高质量Python代码编写的5个优化技巧
Nov 16 Python
利用Django内置的认证视图实现用户密码重置功能详解
Nov 24 Python
python卸载后再次安装遇到的问题解决
Jul 10 Python
详解Python用三种方式统计词频的方法
Jul 29 Python
Python迭代器iterator生成器generator使用解析
Oct 24 Python
Python使用requests xpath 并开启多线程爬取西刺代理ip实例
Mar 06 Python
python如何为list实现find方法
May 30 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编写发红包程序
2015/07/22 PHP
详解PHP序列化反序列化的方法
2015/10/27 PHP
PHP的时间戳与具体时间转化的简单实现
2016/06/13 PHP
tp5实现微信小程序多图片上传到服务器功能
2018/07/16 PHP
屏蔽Flash右键信息的js代码
2010/01/17 Javascript
JavaScript中用字面量创建对象介绍
2014/12/31 Javascript
jquery实现仿新浪微博评论滚动效果
2015/08/06 Javascript
jquery中object对象循环遍历的方法
2015/12/18 Javascript
JavaScript动态设置div的样式的方法
2015/12/26 Javascript
jQuery操作属性和样式详解
2016/04/13 Javascript
Node.js下自定义错误类型详解
2016/10/17 Javascript
详解在vue-cli中使用路由
2017/09/25 Javascript
javascript实现电脑和手机版样式切换
2017/11/10 Javascript
详解mpvue开发小程序小总结
2018/07/25 Javascript
解决vuex刷新数据消失问题
2020/11/12 Javascript
python连接mysql数据库示例(做增删改操作)
2013/12/31 Python
python实现的简单窗口倒计时界面实例
2015/05/05 Python
Python实现统计单词出现的个数
2015/05/28 Python
一键搞定python连接mysql驱动有关问题(windows版本)
2016/04/23 Python
Python Sympy计算梯度、散度和旋度的实例
2019/12/06 Python
Django框架教程之中间件MiddleWare浅析
2019/12/29 Python
基于pygame实现童年掌机打砖块游戏
2020/02/25 Python
利用Python发送邮件或发带附件的邮件
2020/11/12 Python
image-set实现Retina屏幕下图片显示详细介绍
2012/12/24 HTML / CSS
css3实现文字扫光渐变动画效果的示例
2017/11/07 HTML / CSS
贺卡寄语大全
2014/04/11 职场文书
《狼和小羊》教学反思
2014/04/20 职场文书
大学社团计划书
2014/05/01 职场文书
幼儿园师德演讲稿
2014/05/06 职场文书
项目合作意向书模板
2014/07/29 职场文书
纺织工程专业推荐信
2014/09/08 职场文书
2015年销售人员工作总结
2015/04/07 职场文书
2015年体检中心工作总结
2015/05/27 职场文书
委托开发合同书(标准版)
2019/08/07 职场文书
Nginx 负载均衡是什么以及该如何配置
2021/03/31 Servers
table不让td文字溢出操作方法
2022/12/24 HTML / CSS