Pandas直接读取sql脚本
作者:小小明
之前有群友反应同事给了他一个几百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脚本相关推荐
- mysql读取sql脚本_Pandas直接读取sql脚本的方法
之前有群友反应同事给了他一个几百MB的sql脚本,导入数据库再从数据库读取数据有点慢,想了解下有没有可以直接读取sql脚本到pandas的方法. 解析sql脚本文本文件替换成csv格式并加载 我考虑了 ...
- 利用pandas读取SQL Sever数据表
python的pandas库读取SQL sever有两种方法.一种使用pymssql,另一种使用sqlalchemy.这里只是将数据库中的表读取为DataFrame,不进行修改等表操作. 目录 pyt ...
- java sql脚本_java执行sql脚本
package com.unmi.db; import java.io.FileInputStream; import java.io.InputStream; import java.sql.Con ...
- java sql脚本_Java 执行 SQL 脚本文件
是拷贝的别人的,以备学习 package com.unmi.db; import java.io.FileInputStream; import java.io.InputStream; import ...
- [转帖]C#执行SQL脚本,读取XML文件
[转帖]C#执行SQL脚本,读取XML文件 需要添加如下引用: using System.IO; using System.Data.SqlClient; using System.Collectio ...
- python读取excel指定列-Python读取excel指定列生成指定sql脚本的方法
需求 最近公司干活,收到一个需求,说是让手动将数据库查出来的信息复制粘贴到excel中,在用excel中写好的公式将指定的两列数据用update这样的语句替换掉. 例如: 有个A库,其中有两个A.01 ...
- goland sql 脚本运行_Flink 1.9 实战:使用 SQL 读取 Kafka 并写入 MySQL
SqlSubmit 的实现 笔者一开始是想用 SQL Client 来贯穿整个演示环节,但可惜 1.9 版本 SQL CLI 还不支持处理 CREATE TABLE 语句.所以笔者就只好自己写了个简单 ...
- 【数据预处理】pandas读取sql数据(支持百万条读取)
主要使用两个pandas方法: 1.read_sql 函数: pandas.read_sql(sql, con, index_col=None, coerce_float=True, params=N ...
- python读取sql_从python读取sql的实例方法
从python读取sql的方法: 1.利用python内置的open函数读入sql文件: 2.利用第三方库pymysql中的connect函数连接mysql服务器: 3.利用第三方库pandas中的r ...
- 计算机目录读取,从项目目录中读取SQL查询文件(Read SQL query file from project directory)...
从项目目录中读取SQL查询文件(Read SQL query file from project directory) 我在Visual Studio项目中放置了3个特别大的SQL查询,位于项目目录中 ...
最新文章
- java简体(繁体)转换器
- 一步一步学Silverlight 2系列(13):数据与通信之WebRequest
- vim常用命令总结 (转)
- linux dns语法检测工具,DNS解析检查工具之nslookup
- Codeforces 1209D Cow and Snacks
- datatables 获取筛选后的数据
- 老化试验机ami怎么寻找过去的数据_广东元耀:您知道塑料臭氧老化试验机检测浓度的方法有哪些吗?...
- insert时调用本身字段_多线程编程时,7件你必须知道的事情
- 【GDB源码编译】GDB源码编译
- 梦幻群侠传5帮派修炼_梦幻群侠传5唯美版
- .Net资源文件全球化
- [No00005A]word多文档合一
- U3D AND UDK 各自特点
- 特效编辑器开发手记3——保存纹理到plist Base64编码与Zip压缩(上源码)
- Windows每月更新补丁离线安装包下载
- matlab的默认复数开方
- iOS APP 启动页和icon图标尺寸
- Android批量打包
- Axure RP8 进度条
- Windows10系统桌面美化,定制自己的专属桌面.