数据的基石:Python中关系型数据库完全解析

🔎大家好,我是ZTLJQ,希望你看完之后,能对你有所帮助,不足请指正!共同学习交流

📝个人主页-ZTLJQ的主页

🎁欢迎各位→点赞👍 + 收藏⭐️ + 留言📝​📣系列果你对这个系列感兴趣的话

专栏 - ​​​​​​Python从零到企业级应用:短时间成为市场抢手的程序员

✔说明⇢本人讲解主要包括Python爬虫、JS逆向、Python的企业级应用

如果你对这个系列感兴趣的话,可以关注订阅哟👋

数据存储的基石

在现代应用程序中,数据是核心资产。无论是用户的个人信息、电子商务的订单记录,还是社交媒体的动态,这些有价值的信息都需要一个可靠、高效的地方进行存储、检索和管理。关系型数据库(Relational Database Management System, RDBMS)凭借其严格的数据结构、强大的查询能力和ACID事务特性,成为了绝大多数应用的首选。

对于Python开发者而言,掌握如何与关系型数据库交互是一项至关重要的技能。本篇博客将从数据库基础讲起,深入探讨Python中操作数据库的各种方式,从直接的SQL执行到高级的对象关系映射(ORM),并结合实际案例,带您构建一个完整的数据驱动应用。


第一部分:关系型数据库核心概念

在深入代码之前,我们需要理解关系型数据库的基本构成要素。

  • 数据库 (Database): 一个容器,用于存储相关的数据集合。
  • 表 (Table): 数据以表格形式存储,类似于Excel电子表格。表由行(记录)和列(字段)组成。
  • 行 (Row/Record): 表中的一条数据记录。例如,用户表中的一行代表一个用户。
  • 列 (Column/Field): 定义了数据的属性。例如,用户表中的"姓名"、"邮箱"列。
  • 主键 (Primary Key): 一个或一组列,其值能够唯一标识表中的每一行。例如,用户ID。
  • 外键 (Foreign Key): 一个表中的列,其值对应另一个表的主键,用于建立表与表之间的关系。例如,订单表中的"用户ID"列是用户表的外键。
  • SQL (Structured Query Language) : 结构化查询语言,是与关系型数据库通信的标准语言。通过SQL,我们可以创建表(CREATE TABLE)、插入数据(INSERT)、查询数据(SELECT)、更新数据(UPDATE)和删除数据(DELETE)。

第二部分:Python原生数据库连接------sqlite3

sqlite3模块是Python标准库的一部分,它提供了对SQLite数据库的原生接口。SQLite是一个轻量级的、无服务器的数据库,非常适合嵌入式应用、移动应用和小型Web项目。

2.1 实战案例:使用sqlite3构建一个图书管理系统

让我们从最基础的方式开始,使用sqlite3模块来创建一个简单的图书管理系统。

第一步:连接数据库并创建表

python 复制代码
import sqlite3

# 连接到数据库 (如果文件不存在,会自动创建)
conn = sqlite3.connect('library.db')

# 创建一个游标对象,用于执行SQL命令
cursor = conn.cursor()

# 定义创建表的SQL语句
create_table_sql = '''
CREATE TABLE IF NOT EXISTS books (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    title TEXT NOT NULL,
    author TEXT NOT NULL,
    isbn TEXT UNIQUE,
    published_year INTEGER,
    genre TEXT
);
'''

# 执行SQL命令
cursor.execute(create_table_sql)

# 提交事务,确保更改被保存到数据库
conn.commit()

print("Database and table created successfully!")

代码解析:

  • sqlite3.connect('library.db'): 连接到名为library.db的数据库文件。如果文件不存在,SQLite会自动创建它。
  • cursor.execute(sql): 游标对象是执行SQL命令的媒介。execute方法用于执行单条SQL语句。
  • PRIMARY KEY AUTOINCREMENT: 指定id列为主键,并且它的值由数据库自动递增生成。
  • UNIQUE: 约束isbn列的值必须是唯一的。
  • conn.commit(): 非常重要!对数据库的任何修改(INSERT, UPDATE, DELETE)都必须通过commit()来提交事务,否则更改不会被永久保存。

第二步:插入数据

python 复制代码
# 插入单条记录
insert_sql = '''
INSERT INTO books (title, author, isbn, published_year, genre)
VALUES (?, ?, ?, ?, ?)
'''
# 使用参数化查询,可以有效防止SQL注入攻击
book_data = ("The Great Gatsby", "F. Scott Fitzgerald", "978-0-7432-7356-5", 1925, "Fiction")
cursor.execute(insert_sql, book_data)

# 插入多条记录
more_books = [
    ("1984", "George Orwell", "978-0-452-28423-4", 1949, "Dystopian Fiction"),
    ("Pride and Prejudice", "Jane Austen", "978-0-14-143951-8", 1813, "Romance"),
    ("To Kill a Mockingbird", "Harper Lee", "978-0-06-112008-4", 1960, "Fiction")
]
cursor.executemany(insert_sql, more_books)

conn.commit()
print("Books inserted successfully!")

代码解析:

  • ? 是参数占位符。在执行SQL时,?会被execute方法的第二个参数(一个元组)中的值替换。这比直接拼接字符串安全得多。
  • executemany(): 用于高效地执行同一条SQL语句多次,适用于批量插入数据。

第三步:查询数据

python 复制代码
# 查询所有书籍
select_all_sql = "SELECT * FROM books;"
cursor.execute(select_all_sql)
all_books = cursor.fetchall()

print("\nAll Books:")
for book in all_books:
    print(f"ID: {book[0]}, Title: {book[1]}, Author: {book[2]}")

# 查询特定条件的书籍
select_by_author_sql = "SELECT * FROM books WHERE author = ?;"
cursor.execute(select_by_author_sql, ("George Orwell",))
orwell_books = cursor.fetchall()

print("\nBooks by George Orwell:")
for book in orwell_books:
    print(f"- {book[1]} ({book[3]})") # book[1]是标题, book[3]是年份

# 查询并获取单条记录
select_one_sql = "SELECT * FROM books WHERE title LIKE ?;"
cursor.execute(select_one_sql, ("%Pride%",))
one_book = cursor.fetchone()
if one_book:
    print(f"\nFound one book matching 'Pride': {one_book[1]}")

代码解析:

  • fetchall(): 获取所有查询结果,返回一个元组列表。
  • fetchone(): 获取查询结果的下一行,如果没有更多行,则返回None
  • LIKE '%Pride%': SQL中的模糊查询,%是通配符,表示任意字符。

第四步:更新和删除数据

python 复制代码
# 更新数据
update_sql = "UPDATE books SET genre = ? WHERE title = ?;"
cursor.execute(update_sql, ("Classic Literature", "1984"))
conn.commit()
print("\nBook '1984' genre updated.")

# 删除数据
delete_sql = "DELETE FROM books WHERE title = ?;"
cursor.execute(delete_sql, ("To Kill a Mockingbird",))
conn.commit()
print("Book 'To Kill a Mockingbird' deleted.")

# 再次查询所有书籍以验证更改
cursor.execute("SELECT * FROM books;")
remaining_books = cursor.fetchall()
print("\nRemaining Books after deletion:")
for book in remaining_books:
    print(f"ID: {book[0]}, Title: {book[1]}, Author: {book[2]}")

# 最后,关闭游标和连接
cursor.close()
conn.close()

代码解析:

  • UPDATEDELETE语句同样需要WHERE子句来指定操作的目标,否则会更新或删除所有行。
  • cursor.close()conn.close()是良好的编程习惯,用于释放数据库连接资源。

第三部分:高级抽象------对象关系映射(ORM)与SQLAlchemy

直接使用SQL虽然灵活,但当项目变得复杂时,手动编写和管理SQL语句会变得繁琐且容易出错。**对象关系映射(Object-Relational Mapping, ORM)**技术应运而生。它允许我们用Python类来定义数据库表结构,用类的实例来表示表中的记录,从而可以用面向对象的方式来操作数据库。

SQLAlchemy (pip install sqlalchemy) 是Python中最强大、最灵活的ORM库。

3.1 实战案例:使用SQLAlchemy重写图书管理系统

我们将用SQLAlchemy来重构上面的图书管理系统。

第一步:定义模型

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

# 创建一个基类,我们的模型将继承自这个基类
Base = declarative_base()

# 定义Book模型类
class Book(Base):
    __tablename__ = 'books' # 指定对应的数据库表名

    id = Column(Integer, primary_key=True, autoincrement=True)
    title = Column(String, nullable=False)
    author = Column(String, nullable=False)
    isbn = Column(String, unique=True)
    published_year = Column(Integer)
    genre = Column(String)

    def __repr__(self):
        return f"<Book(title='{self.title}', author='{self.author}')>"

代码解析:

  • declarative_base(): SQLAlchemy的声明式基类,所有模型类都要继承它。
  • __tablename__: 类变量,定义了该模型映射到的数据库表的名称。
  • Column(...): 定义了表中的列。Integer, String是数据类型。primary_key, nullable, unique等是列的约束和属性。
  • __repr__: 定义了对象的字符串表示形式,方便调试。

第二步:创建引擎和会话

python 复制代码
​
# 创建数据库引擎 (这里使用SQLite)
engine = create_engine('sqlite:///library_orm.db', echo=True) # echo=True 会打印执行的SQL语句

# 创建所有表 (如果表不存在)
Base.metadata.create_all(engine)

# 创建会话工厂
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)

# 创建一个会话实例 (相当于之前的cursor)
db_session = SessionLocal()

​

代码解析:

  • create_engine(): 创建一个数据库引擎,它负责与数据库进行通信。URL sqlite:///library_orm.db指定了数据库的类型和位置。
  • echo=True: 一个非常有用的调试选项,它会将所有执行的SQL语句打印到控制台。
  • Base.metadata.create_all(engine): 这行代码会扫描所有继承自Base的模型类,并在数据库中创建对应的表(如果表还不存在)。
  • sessionmaker(): 创建一个会话工厂,用于生成与数据库交互的会话(Session)对象。

第三步:使用ORM进行CRUD操作

python 复制代码
try:
    # --- CREATE (创建) ---
    # 创建一个Book对象
    new_book = Book(
        title="Brave New World",
        author="Aldous Huxley",
        isbn="978-0-06-085052-4",
        published_year=1932,
        genre="Science Fiction"
    )
    # 将对象添加到会话中
    db_session.add(new_book)
    # 提交事务
    db_session.commit()
    print(f"Book '{new_book.title}' added via ORM.")

    # --- READ (读取) ---
    # 查询所有书籍
    all_books_orm = db_session.query(Book).all()
    print("\nAll Books (via ORM):")
    for book in all_books_orm:
        print(book)

    # 查询特定作者的书籍
    orwell_books_orm = db_session.query(Book).filter(Book.author == "George Orwell").all()
    print("\nBooks by George Orwell (via ORM):")
    for book in orwell_books_orm:
        print(f"- {book.title} ({book.published_year})")

    # 查询单个对象
    specific_book = db_session.query(Book).filter(Book.title == "1984").first()
    if specific_book:
        print(f"\nFound book: {specific_book}")

    # --- UPDATE (更新) ---
    book_to_update = db_session.query(Book).filter(Book.title == "1984").first()
    if book_to_update:
        book_to_update.genre = "Classic Dystopian Fiction"
        db_session.commit() # 提交更改
        print(f"\nBook '{book_to_update.title}' genre updated via ORM.")

    # --- DELETE (删除) ---
    book_to_delete = db_session.query(Book).filter(Book.title == "To Kill a Mockingbird").first()
    if book_to_delete:
        db_session.delete(book_to_delete)
        db_session.commit() # 提交删除
        print(f"Book '{book_to_delete.title}' deleted via ORM.")
    else:
        print("\nBook 'To Kill a Mockingbird' not found for deletion.")

except Exception as e:
    # 如果发生错误,回滚事务
    db_session.rollback()
    print(f"An error occurred: {e}")
finally:
    # 关闭会话
    db_session.close()

代码解析:

  • db_session.add(obj): 将一个Python对象(Book实例)标记为"待新增"。
  • db_session.query(Model): 开始构建一个查询。.filter(), .all(), .first(), .one_or_none()等方法用于构建和执行查询。
  • db_session.commit(): 提交会话中的所有更改到数据库。
  • db_session.rollback(): 在发生错误时,撤销所有未提交的更改,保证数据一致性。这是使用ORM进行事务管理的重要环节。
  • 核心思想: ORM将复杂的SQL操作封装成了直观的Python对象操作,极大地提高了开发效率和代码的可读性。

第四部分:连接MySQL和PostgreSQL

sqlite3模块只适用于SQLite。对于更大型的项目,我们通常会使用MySQL或PostgreSQL。这时,你需要安装相应的驱动程序。

  • MySQL : pip install PyMySQLpip install mysqlclient
  • PostgreSQL : pip install psycopg2-binary

然后,只需更改create_engine中的URL即可。

python 复制代码
# 连接MySQL
mysql_engine = create_engine('mysql+pymysql://username:password@host:port/database_name')

# 连接PostgreSQL
pg_engine = create_engine('postgresql+psycopg2://username:password@host:port/database_name')

其余的ORM操作(模型定义、查询、增删改)完全相同。


第五部分:最佳实践与注意事项
  1. 使用连接池 : SQLAlchemy的引擎默认包含一个连接池,可以有效管理数据库连接,避免频繁创建和销毁连接带来的性能损耗。
  2. 参数化查询: 无论是使用原生SQL还是ORM,都必须使用参数化查询来防止SQL注入攻击。
  3. 事务管理 : 对于涉及多个操作的业务逻辑,务必使用事务(commit/rollback)来保证数据的原子性。
  4. 索引 : 为经常用于查询条件的列(如WHERE, ORDER BY, JOIN子句中的列)创建索引,可以显著提升查询速度。
  5. 选择合适的工具 : 对于简单、快速的脚本,sqlite3原生模块足够了。对于复杂的、需要团队协作的Web应用,ORM(如SQLAlchemy)是更好的选择。
相关推荐
夏霞2 小时前
c# signlar 客户端传递参数给服务端配置方法
开发语言·c#
迷藏4942 小时前
**发散创新:基于 Rust的开源权限管理系统设计与实战**在现代软件架构中,**权限控制**早已不
java·开发语言·rust·开源
升鲜宝供应链及收银系统源代码服务2 小时前
《IntelliJ + Claude Code + Gemini + ChatGPT 实战配置手册升鲜宝》
java·前端·数据库·chatgpt·供应链系统·生鲜配送
FreakStudio2 小时前
lvgl-micropython、lv_micropython和lv_binding_micropython到底啥关系?一文读懂
python·单片机·嵌入式·面向对象·电子diy
2301_818419013 小时前
C++中的解释器模式变体
开发语言·c++·算法
跟着珅聪学java3 小时前
js编写中文转unicode 教程
前端·javascript·数据库
小江的记录本3 小时前
【Redis】Redis全方位知识体系(附《Redis常用命令速查表(完整版)》)
java·数据库·redis·后端·python·spring·缓存
摇滚侠3 小时前
Java 项目《谷粒商城-1》架构师级Java 项目实战,对标阿里 P6-P7,全网最强,实操版本
java·开发语言
dinl_vin3 小时前
Python 数据分析入门系列(一):从NumPy开始
python·数据分析·numpy