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 相关文章推荐
使用Pyrex来扩展和加速Python程序的教程
Apr 13 Python
python实现计算倒数的方法
Jul 11 Python
python 文件操作api(文件操作函数)
Aug 28 Python
Python 隐藏输入密码时屏幕回显的实例
Feb 19 Python
基于Django静态资源部署404的解决方法
Jul 28 Python
详解Django-channels 实现WebSocket实例
Aug 22 Python
Python的bit_length函数来二进制的位数方法
Aug 27 Python
Python 使用 Pillow 模块给图片添加文字水印的方法
Aug 30 Python
Pytorch修改ResNet模型全连接层进行直接训练实例
Sep 10 Python
python脚本后台执行方式
Dec 21 Python
Python 如何安装Selenium
May 06 Python
python获取字符串中的email
Mar 31 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 MemCached高级缓存配置图文教程
2010/08/05 PHP
关于PHP中Session文件过多的问题及session文件保存位置
2016/03/17 PHP
PHP使用HTML5 FormData对象提交表单操作示例
2019/07/02 PHP
JS Array对象入门分析
2008/10/30 Javascript
javaScript Array(数组)相关方法简述
2009/07/25 Javascript
dropdownlist之间的互相联动实现(显示与隐藏)
2009/11/24 Javascript
分享10篇优秀的jQuery幻灯片制作教程及应用案例
2011/04/16 Javascript
JavaScript中prototype为对象添加属性的误区介绍
2013/10/15 Javascript
Javascript遍历table中的元素示例代码
2014/07/08 Javascript
JavaScript更改字符串的大小写
2015/05/07 Javascript
Javascript 数组去重的方法(四种)详解及实例代码
2016/11/24 Javascript
Vue数据驱动模拟实现1
2017/01/11 Javascript
手机注册发送验证码倒计时的简单实例
2017/11/15 Javascript
vue组件通信传值操作示例
2019/01/08 Javascript
解决layui的使用以及针对select、radio等表单组件不显示的问题
2019/09/05 Javascript
Node.js操作MongoDB数据库实例分析
2020/01/19 Javascript
Vue切换组件实现返回后不重置数据,保留历史设置操作
2020/07/21 Javascript
Python学习笔记之常用函数及说明
2014/05/23 Python
Python解析命令行读取参数--argparse模块使用方法
2018/01/23 Python
python处理excel绘制雷达图
2019/10/18 Python
浅谈python print(xx, flush = True) 全网最清晰的解释
2020/02/21 Python
Python多线程正确用法实例解析
2020/05/30 Python
python爬虫快速响应服务器的做法
2020/11/24 Python
python连接手机自动搜集蚂蚁森林能量的实现代码
2021/02/24 Python
使用Python快速打开一个百万行级别的超大Excel文件的方法
2021/03/02 Python
css3实现3d旋转动画特效
2015/03/10 HTML / CSS
SISLEY希思黎官方旗舰店:享誉全球的奢华植物美容品牌
2018/04/25 全球购物
美国气象仪器、花园装饰和墙壁艺术商店:Wind & Weather
2019/05/29 全球购物
阿巴庭院:Abba Patio
2019/06/18 全球购物
后勤副校长自我鉴定
2013/10/13 职场文书
乔丹名人堂演讲稿
2014/05/24 职场文书
教研处工作方案
2014/05/26 职场文书
“向国旗敬礼”主题班会活动设计方案
2014/09/27 职场文书
幼儿园安全管理制度
2015/08/05 职场文书
读《方与圆》有感:交友方圆有度
2020/01/14 职场文书
Win11软件图标固定到任务栏
2022/04/19 数码科技