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的Tornado框架中实现简单的在线代理的教程
May 02 Python
python通过加号运算符操作列表的方法
Jul 28 Python
实例Python处理XML文件的方法
Aug 31 Python
Python实现随机生成有效手机号码及身份证功能示例
Jun 05 Python
浅谈Python实现Apriori算法介绍
Dec 20 Python
Python动态赋值的陷阱知识点总结
Mar 17 Python
python登录WeChat 实现自动回复实例详解
May 28 Python
python加载自定义词典实例
Dec 06 Python
python 数据分析实现长宽格式的转换
May 18 Python
Softmax函数原理及Python实现过程解析
May 22 Python
python glom模块的使用简介
Apr 13 Python
python 网络编程要点总结
Jun 18 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下实现折线图效果的代码
2007/04/28 PHP
PHP 反射机制实现动态代理的代码
2008/10/22 PHP
php面向对象全攻略 (十七) 自动加载类
2009/09/30 PHP
超级简单的php+mysql留言本源码
2009/11/11 PHP
PHP实现图片不变型裁剪及图片按比例裁剪的方法
2016/01/14 PHP
注释PHP和html混合代码的小技巧(分享)
2016/11/03 PHP
windows下的WAMP环境搭建图文教程(推荐)
2017/07/27 PHP
Windows Live的@live.com域名注册漏洞 利用代码
2006/12/27 Javascript
wordpress之js库集合研究介绍
2007/08/17 Javascript
JavaScript 学习笔记(十六) js事件
2010/02/01 Javascript
json-lib出现There is a cycle in the hierarchy解决办法
2010/02/24 Javascript
jquery和雅虎的yql服务实现天气预报服务示例
2014/02/08 Javascript
Javascript中的几种URL编码方法比较
2015/01/23 Javascript
Node.js实用代码段之正确拼接Buffer
2016/03/17 Javascript
终于实现了!精彩的jquery弹幕效果
2016/07/18 Javascript
Bootstrap 3浏览器兼容性问题及解决方案
2017/04/11 Javascript
详解vue-router 2.0 常用基础知识点之router.push()
2017/05/10 Javascript
vue.js 获取当前自定义属性值
2017/06/01 Javascript
JS实现留言板功能
2017/06/17 Javascript
解决Vue使用mint-ui loadmore实现上拉加载与下拉刷新出现一个页面使用多个上拉加载后冲突问题
2017/11/07 Javascript
jQuery.Sumoselect插件实现下拉复选框效果
2017/11/09 jQuery
Vue 实现从小到大的横向滑动效果详解
2019/10/16 Javascript
jQuery HTML获取内容和属性操作实例分析
2020/05/20 jQuery
15个简单的JS编码标准让你的代码更整洁(小结)
2020/07/16 Javascript
vue中渲染对象中属性时显示未定义的解决
2020/07/31 Javascript
pandas使用get_dummies进行one-hot编码的方法
2018/07/10 Python
在Python中将函数作为另一个函数的参数传入并调用的方法
2019/01/22 Python
python turtle工具绘制四叶草的实例分享
2020/02/14 Python
Senreve官网:美国旧金山的奢侈手袋品牌
2019/03/21 全球购物
什么是Oracle的后台进程background processes?都有哪些后台进程?
2012/04/26 面试题
Tomcat的缺省是多少,怎么修改
2014/04/09 面试题
学生自我鉴定模板
2013/12/30 职场文书
工业自动化专业自荐信范文
2014/04/10 职场文书
创先争优活动心得体会
2014/09/04 职场文书
事业单位岗位说明书
2015/10/08 职场文书
html用代码制作虚线框怎么做? dw制作虚线圆圈的技巧
2022/12/24 HTML / CSS