作者:小小明

之前有群友反应同事给了他一个几百MB的sql脚本,导入数据库再从数据库读取数据有点慢,想了解下有没有可以直接读取sql脚本到pandas的方法。

解析sql脚本文本文件替换成csv格式并加载

我考虑了一下sql脚本也就只是一个文本文件而已,而且只有几百MB,现代的机器足以把它一次性全部加载到内存中,使用python来处理也不会太慢。

我简单研究了一下sql脚本的导出格式,并根据格式写出了以下sql脚本的读取方法。

注意:该读取方法只针对SQLyog导出的mysql脚本测试,其他数据库可能代码需要根据实际情况微调。

读取方法:

from io import StringIO
import pandas as pd
import redef read_sql_script_all(sql_file_path: str, quotechar="'") -> (str, dict):with open(sql_file_path, encoding="utf-8") as f:sql_txt = f.read()sql_txt = re.sub("\s+", " ", sql_txt)end_pos = -1df_dict = {}insert_check = re.compile(r"insert +into +`?(\w+?)`? *\(", re.I | re.A)while True:match_obj = insert_check.search(sql_txt, end_pos+1)if not match_obj:breaktable_name = match_obj.group(1)start_pos = match_obj.span()[1]+1end_pos = sql_txt.find(";", start_pos)tmp = re.sub(r"\)( *values *|, *)\(", "\n",sql_txt[start_pos:end_pos], flags=re.I)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脚本:

其中的表名是index_test

df_dict = read_sql_script_all("D:/tmp/test.sql")
df = df_dict['index_test']
df.head(10)

结果:

可以看到能顺利的直接从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()sql_txt = re.sub("\s+", " ", sql_txt)end_pos = -1dfs = []while True:match_obj = insert_check.search(sql_txt, end_pos+1)if not match_obj:breakstart_pos = match_obj.span()[1]+1end_pos = sql_txt.find(";", start_pos)if table_name != match_obj.group(1):continuetmp = re.sub(r"\)( *values *|, *)\(", "\n",sql_txt[start_pos:end_pos], flags=re.I)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()

结果:

将sql脚本转换为sqlite格式并通过本地sql连接读取

在写完上面的方法后,我又想到另一种解决思路,就是将sql脚本转换成sqlite语法的sql语句,然后直接加载。各种类型的数据库的sql语句变化较大,下面的方法仅针对SQLyog导出的mysql脚本测试通过,如果是其他的数据库,可能下面的方法仍然需要微调。最好是先自行将sql脚本转换为sqlite语法的sql语句后,再使用我写的方法加载。

加载sql脚本的方法:

from sqlalchemy import create_engine
import pandas as pd
import redef 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 = -1while 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:breaktablenames = [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脚本相关推荐

  1. mysql读取sql脚本_Pandas直接读取sql脚本的方法

    之前有群友反应同事给了他一个几百MB的sql脚本,导入数据库再从数据库读取数据有点慢,想了解下有没有可以直接读取sql脚本到pandas的方法. 解析sql脚本文本文件替换成csv格式并加载 我考虑了 ...

  2. 利用pandas读取SQL Sever数据表

    python的pandas库读取SQL sever有两种方法.一种使用pymssql,另一种使用sqlalchemy.这里只是将数据库中的表读取为DataFrame,不进行修改等表操作. 目录 pyt ...

  3. java sql脚本_java执行sql脚本

    package com.unmi.db; import java.io.FileInputStream; import java.io.InputStream; import java.sql.Con ...

  4. java sql脚本_Java 执行 SQL 脚本文件

    是拷贝的别人的,以备学习 package com.unmi.db; import java.io.FileInputStream; import java.io.InputStream; import ...

  5. [转帖]C#执行SQL脚本,读取XML文件

    [转帖]C#执行SQL脚本,读取XML文件 需要添加如下引用: using System.IO; using System.Data.SqlClient; using System.Collectio ...

  6. python读取excel指定列-Python读取excel指定列生成指定sql脚本的方法

    需求 最近公司干活,收到一个需求,说是让手动将数据库查出来的信息复制粘贴到excel中,在用excel中写好的公式将指定的两列数据用update这样的语句替换掉. 例如: 有个A库,其中有两个A.01 ...

  7. goland sql 脚本运行_Flink 1.9 实战:使用 SQL 读取 Kafka 并写入 MySQL

    SqlSubmit 的实现 笔者一开始是想用 SQL Client 来贯穿整个演示环节,但可惜 1.9 版本 SQL CLI 还不支持处理 CREATE TABLE 语句.所以笔者就只好自己写了个简单 ...

  8. 【数据预处理】pandas读取sql数据(支持百万条读取)

    主要使用两个pandas方法: 1.read_sql 函数: pandas.read_sql(sql, con, index_col=None, coerce_float=True, params=N ...

  9. python读取sql_从python读取sql的实例方法

    从python读取sql的方法: 1.利用python内置的open函数读入sql文件: 2.利用第三方库pymysql中的connect函数连接mysql服务器: 3.利用第三方库pandas中的r ...

  10. 计算机目录读取,从项目目录中读取SQL查询文件(Read SQL query file from project directory)...

    从项目目录中读取SQL查询文件(Read SQL query file from project directory) 我在Visual Studio项目中放置了3个特别大的SQL查询,位于项目目录中 ...

最新文章

  1. java简体(繁体)转换器
  2. 一步一步学Silverlight 2系列(13):数据与通信之WebRequest
  3. vim常用命令总结 (转)
  4. linux dns语法检测工具,DNS解析检查工具之nslookup
  5. Codeforces 1209D Cow and Snacks
  6. datatables 获取筛选后的数据
  7. 老化试验机ami怎么寻找过去的数据_广东元耀:您知道塑料臭氧老化试验机检测浓度的方法有哪些吗?...
  8. insert时调用本身字段_多线程编程时,7件你必须知道的事情
  9. 【GDB源码编译】GDB源码编译
  10. 梦幻群侠传5帮派修炼_梦幻群侠传5唯美版
  11. .Net资源文件全球化
  12. [No00005A]word多文档合一
  13. U3D AND UDK 各自特点
  14. 特效编辑器开发手记3——保存纹理到plist Base64编码与Zip压缩(上源码)
  15. Windows每月更新补丁离线安装包下载
  16. matlab的默认复数开方
  17. iOS APP 启动页和icon图标尺寸
  18. Android批量打包
  19. Axure RP8 进度条
  20. Windows10系统桌面美化,定制自己的专属桌面.

热门文章

  1. python之手机号码的验证查询
  2. SQL Server查询语句
  3. python派森编程软件_派森Python
  4. Redis入门(windows)
  5. python打开excel执行vba代码_xlwings:操作Excel,通过宏调用Pyhton(VBA调Python)-Go语言中文社区...
  6. 写给自己的CDSN账号
  7. Python 第六节课
  8. 基于pyqt5的Demo软件开发
  9. BlenderPython (三)bpy模块
  10. Python之XML模块