使用pandas读取.sql文件遇UnicodeDecodeError及表数据读取问题
SQL文件读取:编码错误修复与指定表读取方案
一、修复UnicodeDecodeError编码错误
你之前的问题出在编码参数传错了地方:pd.read_sql_query根本没有encoding参数,这个参数应该传给打开文件的open()函数——错误是读取文件时的编码解码失败,和执行SQL无关。另外你代码里的connection = 'database'是无效的,必须用SQLAlchemy创建真实的数据库连接对象。
修改后的代码(先解决编码问题):
with open('/filepath/mydata.sql', 'r', encoding='unicode_escape') as query: sql_content = query.read() # 后续需要连接到实际数据库才能执行SQL,比如临时创建的SQLite/MySQL
如果unicode_escape还是不行,可以尝试兼容性更强的latin-1编码:
with open('/filepath/mydata.sql', 'r', encoding='latin-1') as query: sql_content = query.read()
二、从SQL文件中读取指定表的数据
mysqldump导出的.sql文件是建表语句+批量插入语句,不是查询语句,直接用pd.read_sql_query执行整个文件行不通。推荐两种方案:
方案1:创建临时数据库导入后读取(推荐,适合大体积数据)
这是最稳妥的方式,利用数据库引擎处理数据,避免内存爆炸:
创建临时数据库并导入SQL文件
用SQLite(无需服务,轻量便捷)的话,命令行执行:# 创建空的SQLite数据库文件 sqlite3 temp.db # 在SQLite交互界面导入SQL文件 .read /filepath/mydata.sql # 输入.exit退出如果用MySQL,先创建数据库再导入:
mysql -u 你的用户名 -p -e "CREATE DATABASE temp_db;" mysql -u 你的用户名 -p temp_db < /filepath/mydata.sql用Pandas读取指定表
连接临时数据库后,就可以用你熟悉的方式读取:from sqlalchemy import create_engine import pandas as pd # 连接SQLite临时库 engine = create_engine('sqlite:///temp.db') # 直接读取整个表,支持chunksize分块 df_chunks = pd.read_sql_table('目标表名', con=engine, chunksize=100) # 或者用自定义查询 df_chunks = pd.read_sql("SELECT * FROM 目标表名 LIMIT 1000", con=engine, chunksize=100)
方案2:解析SQL文件提取指定表数据(适合中小型数据)
如果环境不允许创建数据库,可以用sqlparse库解析SQL文件,提取目标表的插入数据:
先安装sqlparse:pip install sqlparse
然后用下面的代码提取:
import sqlparse import pandas as pd def get_table_data(sql_path, target_table): # 提取目标表的列名 columns = [] # 提取目标表的插入数据 data_rows = [] with open(sql_path, 'r', encoding='unicode_escape') as f: sql_content = f.read() # 拆分SQL语句 statements = sqlparse.split(sql_content) for stmt in statements: parsed = sqlparse.parse(stmt)[0] stmt_type = parsed.get_type() # 提取CREATE TABLE中的列名 if stmt_type == 'CREATE' and target_table.lower() in str(parsed).lower(): for token in parsed.tokens: if isinstance(token, sqlparse.sql.Parenthesis): for item in token.tokens: if isinstance(item, sqlparse.sql.Identifier): columns.append(item.get_real_name()) continue # 提取INSERT INTO中的数据 if stmt_type == 'INSERT' and target_table.lower() in str(parsed).lower(): # 截取VALUES后面的内容 values_part = str(parsed).split('VALUES')[1].strip().rstrip(';') # 转换为列表(仅当SQL格式规范时使用,避免安全风险) rows = eval(values_part) data_rows.extend(rows) return pd.DataFrame(data_rows, columns=columns) # 使用示例 df = get_table_data('/filepath/mydata.sql', '你的目标表名')
注意:这个方法对SQL格式要求较高,大体积数据还是用方案1更稳定。
内容的提问来源于stack exchange,提问作者Luis Enriquez-Contreras
相关产品推荐
相关产品推荐

