导出时数据库连接切换需新建连接或显式设connection.database;跨表查询须SQL层别名避免列冲突;写Excel应先数据后表头并冻结窗格;大表须chunksize分批读取防内存溢出。
导出时数据库连接切换不生效,mysql.connector 或 sqlalchemy 复用连接对象
跨库本质是换 database 参数,不是换 host/port。常见错误是复用已建立的连接对象却没重连,导致仍查原库。
实操建议:
- 每次切换库都新建连接,或显式调用
connection.database = 'new_db'(仅部分驱动支持) - 用
sqlalchemy时,create_engine('mysql://u:p@h:3306/db1')中的db1是默认库,执行跨库 SQL 需写全名:SELECT * FROM db2.table_name - 避免用
USE db2切库命令——它只对当前连接会话临时生效,且在连接池场景下不可靠
pandas.read_sql 跨表联合查询字段冲突,列名重复导致 ValueError: Duplicate column names
多表 JOIN 后若存在同名列(如两表都有 id),pandas 默认不重命名,直接报错。
实操建议:
- SQL 层就做别名:写成
SELECT t1.id AS t1_id, t2.id AS t2_id, ... - 不用
*,明确列出所有字段,控制命名空间 - 如果必须用
*,可在读取后手动处理:df.columns = [f'{i}_{c}' for i, c in enumerate(df.columns)](仅调试用,不推荐生产)
结构与数据分离:用 openpyxl 写入表头+数据,但样式/冻结窗格失效
直接用 df.to_excel() 会把结构和数据混在一起写,后续加样式、冻结首行等操作困难;而纯 openpyxl 手动写又容易漏掉数据类型推断(如日期变数字)。
实操建议:
- 先用
df.to_excel(writer, index=False, header=False)只写数据,跳过表头 - 再用
writer.sheets['Sheet1'].append(list(df.columns))插入表头到第一行 - 设置冻结:
writer.sheets['Sheet1'].freeze_panes = 'A2' - 注意:
openpyxl不自动识别 pandas 的datetime64类型,需提前转为 Pythondatetime或用dt.strftime()
导出大表时内存爆掉,pd.read_sql 一次性加载全部数据
跨库跨表查询结果动辄百万行,全量载入内存再写 Excel,极易触发 MemoryError,尤其 Windows 下 32 位 Python 更敏感。
实操建议:
- 用
chunksize分批读取:for chunk in pd.read_sql(sql, conn, chunksize=5000): ... - 每批用
ExcelWriter的mode='a'追加(注意:仅openpyxl引擎支持,xlsxwriter不支持追加) - 更稳的做法:先写表头,再循环写数据块,用
workbook和worksheet底层 API 控制写入位置(避开pandas封装)
结构和数据分离的关键不在“怎么拆”,而在“谁负责定义结构”。很多人以为表头就是列名,其实主键、索引、空值约束、字段注释这些元信息也属于结构——它们不会进 Excel 单元格,但决定你后续能不能无损还原回库。漏掉这一层,所谓分离只是表面功夫。


















