15、Python 访问数据库

一、概述

Python操作数据库一般有三种方式:

  1. 原生驱动直接写SQL:sqlite3(内置SQLite)、pymysql(MySQL)
  2. ORM框架 SQLAlchemy:用Python对象映射数据库表,减少手写SQL,适配多种数据库
  3. 适用场景:小测试用SQLite;业务存储用MySQL;项目开发优先SQLAlchemy

遵循数据库通用规范:先建连接 → 获取游标 → 执行SQL → 提交事务 → 关闭游标和连接


二、使用 SQLite

SQLite是文件型数据库,Python内置sqlite3模块,无需额外安装,不需要单独启动服务,适合本地测试、小型数据存储。

基础示例

复制代码
import sqlite3

# 1. 连接数据库,不存在则自动创建文件 test.db
conn = sqlite3.connect("test.db")
# 2. 获取游标
cursor = conn.cursor()

# 建表
cursor.execute('''
CREATE TABLE IF NOT EXISTS user (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    name TEXT NOT NULL,
    age INTEGER
)
''')

# 插入单条数据
cursor.execute("INSERT INTO user(name, age) VALUES (?, ?)", ("zhangsan", 20))
# 批量插入
cursor.executemany("INSERT INTO user(name, age) VALUES (?, ?)", [
    ("lisi", 22),
    ("wangwu", 21)
])

# 查询
cursor.execute("SELECT * FROM user")
print(cursor.fetchall())   # 全部结果
# cursor.fetchone() 取第一条
# cursor.fetchmany(2) 取前2条

# 更新
cursor.execute("UPDATE user SET age=? WHERE name=?", (25, "zhangsan"))
# 删除
cursor.execute("DELETE FROM user WHERE name=?", ("wangwu",))

# 提交事务(DML操作必须commit,SQLite默认事务)
conn.commit()

# 关闭
cursor.close()
conn.close()

占位符:SQLite 使用 ?,不要用字符串拼接SQL,防止SQL注入


三、使用 MySQL

MySQL是C/S架构数据库,需要先安装MySQL服务,Python使用pymysql驱动。

1. 安装

复制代码
pip install pymysql

2. 基础示例

复制代码
import pymysql

# 建立连接
conn = pymysql.connect(
    host="127.0.0.1",
    port=3306,
    user="root",
    password="你的密码",
    database="test_db",
    charset="utf8mb4"
)
cursor = conn.cursor()

# 建表
cursor.execute('''
CREATE TABLE IF NOT EXISTS user(
    id INT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(50),
    age INT
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
''')

# 插入,pymysql占位符是 %s
cursor.execute("INSERT INTO user(name,age) VALUES (%s,%s)", ("zhangsan",20))
conn.commit()

# 查询
cursor.execute("SELECT * FROM user")
print(cursor.fetchall())

cursor.close()
conn.close()

✅ 重点区别:

  • pymysql 占位符是 %s,不是字符串格式化!
  • 必须提前建好数据库(CREATE DATABASE test_db;)
  • 异常场景:网络断开、账号密码错误、库不存在

异常捕获模板

复制代码
import pymysql
try:
    conn = pymysql.connect(...)
    cursor = conn.cursor()
    cursor.execute(sql)
    conn.commit()
except pymysql.MySQLError as e:
    print("数据库错误:", e)
    conn.rollback()  # 出错回滚
finally:
    if conn:
        cursor.close()
        conn.close()

四、使用 SQLAlchemy

SQLAlchemy 是Python最经典的ORM(对象关系映射)框架,一套代码可以切换 SQLite / MySQL / PostgreSQL,不用大量改SQL。 分为两种使用方式:

  1. Core:SQL表达式方式
  2. ORM:面向对象,类映射表(日常开发最常用)

1. 安装

复制代码
pip install sqlalchemy

2. ORM 完整示例(MySQL)

复制代码
from sqlalchemy import create_engine, Column, Integer, String
from sqlalchemy.orm import declarative_base, sessionmaker

# 1. 创建引擎,连接数据库
# mysql+pymysql://user:password@host:port/dbname
engine = create_engine("mysql+pymysql://root:密码@127.0.0.1:3306/test_db")
# SQLite引擎写法:engine = create_engine("sqlite:///test.db")

# 2. 基类,所有模型继承它
Base = declarative_base()

# 3. 定义模型类(对应数据库一张表)
class User(Base):
    __tablename__ = "user"
    id = Column(Integer, primary_key=True, autoincrement=True)
    name = Column(String(50), nullable=False)
    age = Column(Integer)

    def __repr__(self):
        return f"<User(name={self.name}, age={self.age})>"

# 4. 创建表(不存在才创建)
Base.metadata.create_all(engine)

# 5. 创建会话,用来增删改查
Session = sessionmaker(bind=engine)
session = Session()

# 新增
u1 = User(name="zhangsan", age=20)
session.add(u1)
session.add_all([
    User(name="lisi", age=22),
    User(name="wangwu", age=21)
])
session.commit()

# 查询
# 查询所有
res = session.query(User).all()
# 条件查询
res = session.query(User).filter(User.name == "zhangsan").first()
# 模糊查询 filter(User.name.like("%zhang%"))

# 更新
if res:
    res.age = 26
    session.commit()

# 删除
session.delete(res)
session.commit()

session.close()

常用查询语法速记

复制代码
# 等于
filter(User.name == "xxx")
# 大于小于
filter(User.age > 18)
# and / or
from sqlalchemy import or_, and_
filter(or_(User.age>20, User.name=="lisi"))
# 排序
order_by(User.age.desc())
# 分页 offset limit
session.query(User).order_by(User.id).offset(0).limit(10).all()

五、三者对比总结

方式 依赖 优点 缺点 适合场景
sqlite3 内置 零服务、开箱即用 并发弱、不适合多用户 本地缓存、脚本、测试
pymysql原生 需要MySQL服务 灵活,完全掌控SQL 重复样板代码,容易注入,切换数据库改动大 简单脚本、需要精细控制SQL
SQLAlchemy ORM 驱动+框架 面向对象、跨数据库、防注入、代码优雅 有学习成本,复杂SQL性能不如手写 Web项目、后端业务开发

六、重要注意事项

  1. 永远不要字符串拼接SQL,使用参数化查询,防止SQL注入
  2. 写修改操作(insert/update/delete)一定要 commit,异常时 rollback
  3. 用完连接、游标、session要关闭,避免连接泄漏
  4. MySQL注意编码 utf8mb4 支持emoji
  5. SQLAlchemy适合业务开发;报表、超复杂聚合SQL可以用原生SQL
相关推荐
Decay__2 小时前
VMware 安装 SQL Server 双节点 AlwaysOn 可用性组教程 —— WSFC、AG 与侦听器完整部署(系列核心篇)
运维·数据库·sql·mysql·架构
databook3 小时前
时间序列数据,先拆规律还是先查异常
python·数据挖掘·数据分析
茶栀(*´I`*)3 小时前
SQL 性能分析:从慢查询日志到执行计划的完整定位方法
数据库·sql
师夷长技以自愈3 小时前
手搓 AI Agent 第 8 篇:从手写循环到画流程图——LangGraph 封装
人工智能·python
艺杯羹3 小时前
1Panel 装好后 ufw 仍是 inactive:一次服务器安全盲区复盘
服务器·数据库·安全·网络安全·系统架构·实战·1panel
aifannihao4 小时前
Rust 1.100 的 DropGuard:用 Python 实测失败回滚与吞异常
python·rust·异常处理·标准库·contextlib
code2cat4 小时前
【随笔】MCP工具重试:任务已经创建,响应丢了怎么办
数据库·mcp
用户019027581616 小时前
天勤 tqsdk 能做 A 股行情吗?期货强项与股票数据选型
python
wuyk5556 小时前
Spider-第10讲-SQLite持久化与去重
数据库·爬虫·sqlite
2601_967979127 小时前
pip在Python中的9个必须知道的用法
python·pip·版本控制·包管理工具·requirements.txt