自学教程 学编程从这里开始

Pandas 读取 SQL 数据库

简介

Pandas 提供 pandas.read_sql(),可以直接执行 SQL 语句,把查询结果读取为 DataFrame,省去手动循环读取、组装列表的繁琐代码,是数据分析里非常高频的组合方案。

核心函数:

  • pd.read_sql(sql, con):执行 SQL,返回 DataFrame
  • pd.read_sql_table(table_name, con):直接读取整张表(不需要写 select)
  • pd.read_sql_query(sql, con):和 read_sql 基本一致,推荐区分使用

说明:read_sql 在新版本 pandas 内部就是 read_sql_query,为了代码可读性,建议优先使用 read_sql_query。

环境依赖

不同数据库需要不同驱动包:

# MySQL / MariaDB
pip install pandas pymysql sqlalchemy

# PostgreSQL
pip install pandas psycopg2-binary sqlalchemy

# SQL Server
pip install pandas pyodbc sqlalchemy

# SQLite(Python自带,无需额外驱动,仅需sqlalchemy)
pip install pandas sqlalchemy

推荐统一使用 SQLAlchemy 作为连接层,它可以兼容多种数据库,写法统一。

import pandas as pd
from sqlalchemy import create_engine

一、MySQL 示例(最常用)

1. 创建数据库连接引擎

连接字符串格式:

mysql+pymysql://用户名:密码@主机:端口/数据库名?charset=utf8mb4
# 数据库连接信息
user = "root"
password = "123456"
host = "127.0.0.1"
port = 3306
db_name = "test_db"

# 创建引擎
engine = create_engine(f"mysql+pymysql://{user}:{password}@{host}:{port}/{db_name}?charset=utf8mb4")

2. 执行SQL查询,读取到DataFrame

sql = """
SELECT id, order_no, goods_name, qty, price, sale_date
FROM sale_detail
WHERE sale_date >= '2026-01-01'
ORDER BY sale_date DESC
"""

df = pd.read_sql_query(sql, con=engine)
print(df.head())
print(df.dtypes)

3. 直接读取整张表

# 读取 sale_detail 全表
df_all = pd.read_sql_table("sale_detail", con=engine)

4. 带参数查询(防SQL注入,重要)

❌ 不要字符串拼接SQL!容易注入、日期/引号出错。
✅ 使用 SQLAlchemy 参数绑定 :param

sql = """
SELECT * FROM sale_detail
WHERE sale_date >= :start_date AND goods_name = :goods
"""
params = {
    "start_date": "2026-01-01",
    "goods": "笔记本"
}
df = pd.read_sql_query(sql, con=engine, params=params)

二、SQLite 示例(本地文件数据库,无需服务)

适合本地小数据、测试

# sqlite:/// 后面是文件路径,相对/绝对路径均可
engine = create_engine("sqlite:///./test.db")

sql = "SELECT * FROM sale_detail;"
df = pd.read_sql_query(sql, engine)

三、PostgreSQL 示例

engine = create_engine("postgresql://user:password@127.0.0.1:5432/test_db")
df = pd.read_sql_query("SELECT * FROM sale_detail limit 100", engine)

四、分批读取(大数据,避免内存爆掉 chunksize)

数据量很大时,一次性读入内存会 OOM,使用 chunksize 返回迭代器,分批处理:

sql = "SELECT * FROM sale_detail;"

chunk_iter = pd.read_sql_query(sql, con=engine, chunksize=1000)

for chunk_df in chunk_iter:
    # chunk_df 每批1000行
    print("批次数据行数:", len(chunk_df))
    # 在这里做清洗、统计、写入文件等操作

五、把 DataFrame 写入数据库(配套常用)

to_sql,和 read_sql 成对使用

# name:表名;if_exists: replace / append / fail
df.to_sql(
    name="sale_backup",
    con=engine,
    if_exists="append",
    index=False,
    chunksize=1000
)
  • if_exists="replace":删表重建
  • if_exists="append":追加数据(常用)
  • if_exists="fail":表存在就报错(默认)

六、上下文管理(自动关闭连接,推荐写法)

from sqlalchemy import create_engine

engine = create_engine("mysql+pymysql://root:123456@127.0.0.1:3306/test_db?charset=utf8mb4")

with engine.connect() as conn:
    sql = "SELECT * FROM sale_detail limit 100"
    df = pd.read_sql_query(sql, con=conn)

print(df)

七、常见坑点

  1. 字符乱码

    MySQL 连接串必须带上 charset=utf8mb4,支持emoji和全部中文。
  2. SQL注入风险

    禁止 f-string 直接拼接用户输入到SQL,一律用 params 参数传参。
  3. 时间字段读取后变成 object

    可以在SQL里 CAST,或者读取后 pd.to_datetime(df["sale_date"]) 转换。
  4. 大数据直接卡死

    一定要用 chunksize 分批迭代,不要一次性 select * 大表。
  5. to_sql 写入很慢

    调大 chunksize;MySQL 可搭配 pymysql,不要用 mysqldb;生产环境海量数据优先数据库导出方案。
  6. 连接泄露

    优先 with engine.connect(),自动释放连接。

八、API 参数速查表

参数说明
sqlSQL查询字符串
conSQLAlchemy engine / connection 对象
paramsSQL绑定参数字典,安全传参
chunksize分批行数,返回迭代器
index_col指定某一列作为DataFrame索引
parse_dates指定哪些列自动解析为日期,如 parse_dates=["sale_date"]

示例 parse_dates:

df = pd.read_sql_query(sql, engine, parse_dates=["sale_date"])

九、综合实战:读取销售表,统计汇总,导出Excel

和前面《Pandas Excel 文件操作》配套打通

import pandas as pd
from sqlalchemy import create_engine

engine = create_engine("mysql+pymysql://root:123456@127.0.0.1:3306/test_db?charset=utf8mb4")

sql = """
SELECT order_no, goods_name, qty, price, sale_date
FROM sale_detail
WHERE sale_date >= '2026-01-01'
"""
df_sale = pd.read_sql_query(sql, con=engine, parse_dates=["sale_date"])

# 计算金额
df_sale["amount"] = df_sale["qty"] * df_sale["price"]

# 商品汇总
df_goods_sum = df_sale.groupby("goods_name").agg(
    total_qty=("qty", "sum"),
    total_amount=("amount", "sum")
).reset_index()

# 导出到Excel(可接上xlsxwriter进阶报表)
with pd.ExcelWriter("销售汇总报表.xlsx", engine="xlsxwriter") as w:
    df_sale.to_excel(w, sheet_name="原始明细", index=False)
    df_goods_sum.to_excel(w, sheet_name="商品汇总", index=False)

print("报表导出完成")

小结

pd.read_sql_query + SQLAlchemy 是 Pandas 对接数据库的标准方案,一套写法适配 MySQL、PostgreSQL、SQLite 等主流数据库。
流程:建立连接 → SQL查询读取DataFrame → 清洗统计分析 → 可写入数据库 / 导出Excel。

0 条笔记