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中的日志模块logging
Jun 19 Python
各种Python库安装包下载地址与安装过程详细介绍(Windows版)
Nov 02 Python
浅谈django model postgres的json字段编码问题
Jan 05 Python
用 Python 连接 MySQL 的几种方式详解
Apr 04 Python
python3+PyQt5实现拖放功能
Apr 24 Python
对python中的logger模块全面讲解
Apr 28 Python
使用Python实现从各个子文件夹中复制指定文件的方法
Oct 25 Python
Python 监测文件是否更新的方法
Jun 10 Python
python列表每个元素同增同减和列表元素去空格的实例
Jul 20 Python
django组合搜索实现过程详解(附代码)
Aug 06 Python
Django在admin后台集成TinyMCE富文本编辑器的例子
Aug 09 Python
django model的update时auto_now不被更新的原因及解决方式
Apr 01 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 has encountered an Access Violation 错误的解决方法
2010/01/17 PHP
让php处理图片变得简单 基于gb库的图片处理类附实例代码下载
2011/05/17 PHP
PHP Opcache安装和配置方法介绍
2015/05/28 PHP
php获取错误信息的方法
2015/07/17 PHP
关于PHP中字符串与多进制转换函数的实例代码
2016/11/03 PHP
如何优雅的使用 laravel 的 validator验证方法
2018/11/11 PHP
PHP PDO和消息队列的个人理解与应用实例分析
2019/11/25 PHP
jquery validate添加自定义验证规则(验证邮箱 邮政编码)
2013/12/04 Javascript
JS实现图片无间断滚动代码汇总
2014/07/30 Javascript
node.js中的fs.fchmodSync方法使用说明
2014/12/16 Javascript
使用jquery清空、复位整个输入域
2015/04/02 Javascript
基于AngularJS前端云组件最佳实践
2016/10/20 Javascript
javascript实现的图片预览功能
2017/03/25 Javascript
JavaScript 异步调用
2017/10/25 Javascript
Javascript实现运算符重载详解
2018/04/07 Javascript
使用vue cli4.x搭建vue项目的过程详解
2020/05/08 Javascript
vue3+typescript实现图片懒加载插件
2020/10/26 Javascript
Python中的CURL PycURL使用例子
2014/06/01 Python
Python开发中爬虫使用代理proxy抓取网页的方法示例
2017/09/26 Python
利用Tkinter(python3.6)实现一个简单计算器
2017/12/21 Python
PyTorch搭建多项式回归模型(三)
2019/05/22 Python
python求最大值,不使用内置函数的实现方法
2019/07/09 Python
Kears+Opencv实现简单人脸识别
2019/08/28 Python
详解css3中dispaly的Grid布局与Flex布局
2020/09/11 HTML / CSS
尤妮佳moony海外旗舰店:日本殿堂级纸尿裤品牌
2018/02/23 全球购物
新西兰优惠网站:Treat Me
2019/07/04 全球购物
机电专业毕业生推荐信
2013/11/10 职场文书
社区服务标语
2014/07/01 职场文书
初中优秀教师事迹材料
2014/08/18 职场文书
教师节活动总结
2014/08/29 职场文书
专升本学生毕业自我鉴定
2014/10/04 职场文书
党员教师群众路线思想汇报范文
2014/10/28 职场文书
2014年医院科室工作总结
2014/12/20 职场文书
幼儿园中秋节活动总结
2015/03/23 职场文书
装饰施工员岗位职责
2015/04/11 职场文书
庆七一晚会主持词
2015/06/30 职场文书