Python 數(shù)據(jù)庫(kù)操作神器,一文掌握 ORM!
你是否遇到這些問(wèn)題?
- 還在手寫 SQL?數(shù)據(jù)庫(kù)操作太麻煩?
- Django ORM 用過(guò),但想在 Flask 中也用 ORM?
- SQLAlchemy 怎么連接數(shù)據(jù)庫(kù)?如何查詢數(shù)據(jù)?
SQLAlchemy 是 Python 最強(qiáng)大的 ORM 框架,支持 MySQL、PostgreSQL、SQLite、SQL Server 等數(shù)據(jù)庫(kù)。本篇文章帶你 從入門到實(shí)戰(zhàn),徹底掌握 SQLAlchemy!
1. 什么是 SQLAlchemy?為什么要用 ORM?
SQLAlchemy 是 Python 的 ORM(對(duì)象關(guān)系映射)框架,可以用 Python 代碼 直接操作數(shù)據(jù)庫(kù),而 不需要寫 SQL。
為什么要用 ORM?
- 數(shù)據(jù)庫(kù)操作更 Pythonic(面向?qū)ο螅?/li>
- 兼容多種數(shù)據(jù)庫(kù)(MySQL、PostgreSQL、SQLite 等)
- 自動(dòng)生成 SQL,避免 SQL 注入風(fēng)險(xiǎn)
- 更易維護(hù),代碼比 SQL 語(yǔ)句更清晰
傳統(tǒng) SQL 操作(手寫 SQL):
import sqlite3
conn = sqlite3.connect("test.db")
cursor = conn.cursor()
cursor.execute("CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT, age INTEGER)")
cursor.execute("INSERT INTO users (name, age) VALUES ('Alice', 25)")
conn.commit()
cursor.close()
conn.close()
SQLAlchemy 操作(ORM 方式):
from sqlalchemy import create_engine, Column, Integer, String
from sqlalchemy.orm import declarative_base, sessionmaker
engine = create_engine("sqlite:///test.db")
Base = declarative_base()
classUser(Base):
__tablename__ = "users"
id = Column(Integer, primary_key=True)
name = Column(String)
age = Column(Integer)
Base.metadata.create_all(engine)
Session = sessionmaker(bind=engine)
session = Session()
new_user = User(name="Alice", age=25)
session.add(new_user)
session.commit()
SQLAlchemy 讓數(shù)據(jù)庫(kù)操作更清晰、更 Pythonic!
2. 安裝 & 配置 SQLAlchemy
(1) 安裝 SQLAlchemy
pip install sqlalchemy
如果使用 MySQL,需要額外安裝 MySQL 驅(qū)動(dòng):
pip install pymysql
(2) 創(chuàng)建數(shù)據(jù)庫(kù)連接
from sqlalchemy import create_engine
# 連接 SQLite
engine = create_engine("sqlite:///test.db")
# 連接 MySQL(需要安裝 pymysql)
# engine = create_engine("mysql+pymysql://user:password@localhost/dbname")
SQLAlchemy 通過(guò) create_engine() 統(tǒng)一管理數(shù)據(jù)庫(kù)連接!
3. 創(chuàng)建 ORM 模型(定義數(shù)據(jù)表)
定義一個(gè) User 表:
from sqlalchemy import Column, Integer, String
from sqlalchemy.orm import declarative_base
Base = declarative_base()
class User(Base):
__tablename__ = "users"
id = Column(Integer, primary_key=True)
name = Column(String(50), nullable=False)
age = Column(Integer)
# 創(chuàng)建表
Base.metadata.create_all(engine)
ORM 方式定義表結(jié)構(gòu),避免手寫 SQL !
4. CRUD 操作(增刪改查)
(1) 創(chuàng)建數(shù)據(jù)庫(kù)會(huì)話
from sqlalchemy.orm import sessionmaker
Session = sessionmaker(bind=engine)
session = Session()
所有數(shù)據(jù)庫(kù)操作都通過(guò) session 進(jìn)行!
(2) 插入數(shù)據(jù)(Create)
new_user = User(name="Alice", age=25)
session.add(new_user)
session.commit()
使用 session.add() 添加新數(shù)據(jù),commit() 提交!
(3) 查詢數(shù)據(jù)(Read)
- 查詢所有用戶
users = session.query(User).all()
for user in users:
print(user.id, user.name, user.age)
- 按條件查詢
user = session.query(User).filter_by(name="Alice").first()
print(user.id, user.name, user.age)
- 多條件查詢
from sqlalchemy import and_, or_
# 年齡 > 20 且姓名是 Alice
users = session.query(User).filter(and_(User.age > 20, User.name == "Alice")).all()
# 年齡 > 20 或 姓名是 Alice
users = session.query(User).filter(or_(User.age > 20, User.name == "Alice")).all()
filter() 方式類似 SQL WHERE 語(yǔ)句!
(4) 更新數(shù)據(jù)(Update)
user = session.query(User).filter_by(name="Alice").first()
user.age = 30
session.commit()
直接修改對(duì)象屬性,再 commit() 保存!
(5) 刪除數(shù)據(jù)(Delete)
user = session.query(User).filter_by(name="Alice").first()
session.delete(user)
session.commit()
使用 session.delete() 刪除對(duì)象!
5. 進(jìn)階操作:一對(duì)多 & 多對(duì)多
(1) 一對(duì)多關(guān)系(User → Post)
from sqlalchemy import ForeignKey
from sqlalchemy.orm import relationship
class Post(Base):
__tablename__ = "posts"
id = Column(Integer, primary_key=True)
title = Column(String(100))
user_id = Column(Integer, ForeignKey("users.id"))
user = relationship("User", back_populates="posts")
User.posts = relationship("Post", order_by=Post.id, back_populates="user")
relationship() 讓表之間建立關(guān)系,查詢時(shí)更方便!
(2) 多對(duì)多關(guān)系(User ? Course)
from sqlalchemy import Table
# 關(guān)聯(lián)表
user_course = Table(
"user_course", Base.metadata,
Column("user_id", Integer, ForeignKey("users.id")),
Column("course_id", Integer, ForeignKey("courses.id"))
)
classCourse(Base):
__tablename__ = "courses"
id = Column(Integer, primary_key=True)
name = Column(String(100))
users = relationship("User", secondary=user_course, back_populates="courses")
User.courses = relationship("Course", secondary=user_course, back_populates="users")
多對(duì)多關(guān)系通過(guò) secondary 關(guān)聯(lián)表實(shí)現(xiàn)!
6. SQLAlchemy vs 直接寫 SQL,哪種更好?
方式 | ORM(SQLAlchemy) | 手寫 SQL |
代碼可讀性 | ? 高,可維護(hù)性好 | ? 低,SQL 語(yǔ)句較長(zhǎng) |
數(shù)據(jù)庫(kù)兼容性 | ? 兼容 MySQL、PostgreSQL、SQLite | ? 需改寫 SQL 適配不同數(shù)據(jù)庫(kù) |
安全性 | ? 避免 SQL 注入 | ? 需手動(dòng)防 SQL 注入 |
性能 | ? ORM 有一定性能損耗 | ? SQL 執(zhí)行更快 |
開發(fā)效率 | ? 高效,操作數(shù)據(jù)庫(kù)像操作對(duì)象 | ? 需要手寫 SQL |
- 小型項(xiàng)目、簡(jiǎn)單查詢 → ORM 更方便!
- 復(fù)雜查詢、大數(shù)據(jù)量操作 → SQL 更高效!
7. 結(jié)語(yǔ):SQLAlchemy 讓 Python 操作數(shù)據(jù)庫(kù)更簡(jiǎn)單!
- ORM 讓數(shù)據(jù)庫(kù)操作更直觀,不用手寫 SQL!
- SQLAlchemy 適用于大部分項(xiàng)目,靈活易用,功能強(qiáng)大!