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中的模块和包概念介绍
Apr 13 Python
使用Python制作获取网站目录的图形化程序
May 04 Python
Django应用程序中如何发送电子邮件详解
Feb 04 Python
Python学习笔记之解析json的方法分析
Apr 21 Python
python3下实现搜狗AI API的代码示例
Apr 10 Python
详解Django rest_framework实现RESTful API
May 24 Python
python实现windows下文件备份脚本
May 27 Python
python Tcp协议发送和接收信息的例子
Jul 22 Python
python代码打印100-999之间的回文数示例
Nov 24 Python
使用Keras实现简单线性回归模型操作
Jun 12 Python
python实现邮件循环自动发件功能
Sep 11 Python
提高python代码运行效率的一些建议
Sep 29 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之Smarty入门
2007/01/04 PHP
CodeIgniter框架过滤HTML危险代码
2014/06/12 PHP
php输出全球各个时区列表的方法
2015/03/31 PHP
php防止CC攻击代码 php防止网页频繁刷新
2015/12/21 PHP
基于PHP生成简单的验证码
2016/06/01 PHP
laravel实现Auth认证,登录、注册后的页面回跳方法
2019/09/30 PHP
javascript 动态生成私有变量访问器
2009/12/06 Javascript
基于jquery的使ListNav兼容中文首字拼音排序的实现代码
2011/07/10 Javascript
JS 如何获取radio选中后的值及不选择取radio的值
2013/10/28 Javascript
Javascript封装DOMContentLoaded事件实例
2014/06/12 Javascript
什么是 AngularJS?AngularJS简介
2014/12/06 Javascript
原生js仿jquery animate动画效果
2016/07/13 Javascript
vue购物车插件编写代码
2017/11/27 Javascript
基于Vue2.X的路由和钩子函数详解
2018/02/09 Javascript
VUE安装使用教程详解
2019/06/03 Javascript
webpack是如何实现模块化加载的方法
2019/11/06 Javascript
python删除服务器文件代码示例
2018/02/09 Python
用python写扫雷游戏实例代码分享
2018/05/27 Python
Python基于分析Ajax请求实现抓取今日头条街拍图集功能示例
2018/07/19 Python
python爬虫模拟浏览器的两种方法实例分析
2019/12/09 Python
python矩阵运算,转置,逆运算,共轭矩阵实例
2020/05/11 Python
安装不同版本的tensorflow与models方法实现
2021/02/20 Python
HTML5中通过li-canvas轻松实现单图、多图、圆角图绘制,单行文字、多行文字等
2018/11/30 HTML / CSS
html+js 实现markdown编辑器效果
2019/10/23 HTML / CSS
地球鞋加拿大官网:Earth Shoes Canada
2020/11/17 全球购物
LUISAVIAROMA中国官网:时尚奢侈品牌购物网站
2020/11/01 全球购物
数字漫画:comiXology
2020/06/13 全球购物
班长演讲稿范文
2014/04/24 职场文书
中级会计大学生职业生涯规划书
2014/09/16 职场文书
防灾减灾标语
2014/10/07 职场文书
2014年煤矿工人工作总结
2014/12/08 职场文书
入党申请书怎么写?
2019/06/11 职场文书
2019年汽车租赁合同范本!
2019/08/12 职场文书
企业转让协议书(范文2篇)
2019/08/15 职场文书
Java如何实现树的同构?
2021/06/22 Java/Android
自动在Windows中运行Python脚本并定时触发功能实现
2021/09/04 Python