SQLAlchemy Core API:构建 SQL 表达式与数据库抽象层

好,各位观众,欢迎来到今天的“SQLAlchemy Core API:构建 SQL 表达式与数据库抽象层”讲座!今天咱们不讲玄学,只讲干货,带大家一起玩转 SQLAlchemy Core,看看它是如何让咱们跟数据库“谈恋爱”的。

开场白:为啥要学 SQLAlchemy Core?

想象一下,你是个厨师,想做一道美味的菜肴。你有两种选择:

  1. 直接用手抓: 直接写 SQL 语句,像 SELECT * FROM users WHERE age > 25。这很灵活,但也很容易出错,而且代码可读性差。
  2. 用厨房神器: 使用 SQLAlchemy Core,它可以帮你把复杂的 SQL 操作变成 Python 对象,让你像搭积木一样构建 SQL 语句,减少出错的概率,提高代码可读性。

SQLAlchemy Core 就是那个“厨房神器”。它提供了一套强大的 API,让你可以在 Python 中构建 SQL 表达式,并且可以方便地与各种数据库进行交互。

第一部分: SQLAlchemy Core 的核心概念

SQLAlchemy Core 就像一个乐高玩具,由几个核心部件组成:

  • Engine: 数据库连接引擎,负责建立和管理与数据库的连接。
  • MetaData: 数据库元数据,描述数据库的结构,例如表、列、索引等。
  • Table: 表对象,代表数据库中的一个表。
  • Column: 列对象,代表表中的一列。
  • SQL 表达式: 使用 Python 对象构建的 SQL 语句,例如 select(), insert(), update(), delete() 等。
  • Connection: 数据库连接对象,用于执行 SQL 语句。

1. Engine:连接数据库的桥梁

Engine 是 SQLAlchemy 的入口点,它负责建立与数据库的连接。你可以把它想象成一个水龙头,拧开它,水(数据)就哗啦啦地流出来了。

from sqlalchemy import create_engine

# 创建一个 SQLite 数据库引擎 (内存数据库)
engine = create_engine('sqlite:///:memory:')

# 创建一个 PostgreSQL 数据库引擎
# engine = create_engine('postgresql://user:password@host:port/database')

# 创建一个 MySQL 数据库引擎
# engine = create_engine('mysql+pymysql://user:password@host:port/database')

这里 create_engine() 函数接收一个数据库 URL 作为参数。URL 的格式取决于你使用的数据库类型。

2. MetaData:数据库的蓝图

MetaData 对象用于存储数据库的元数据,包括表、列、索引等信息。你可以把它想象成数据库的蓝图,告诉你数据库里有什么东西。

from sqlalchemy import MetaData

metadata = MetaData()

3. Table:表的化身

Table 对象代表数据库中的一个表。你需要定义表的名称、列以及其他约束条件。你可以把它想象成数据库里的一张桌子,上面放着各种东西(数据)。

from sqlalchemy import Table, Column, Integer, String, Identity

users_table = Table(
    'users', metadata,
    Column('id', Integer, Identity(), primary_key=True),
    Column('name', String(50), nullable=False),
    Column('age', Integer)
)

这里我们创建了一个名为 users 的表,它有三个列:id (主键,自动增长)、name (字符串,不能为空) 和 age (整数)。

4. Column:列的代言人

Column 对象代表表中的一列。你需要指定列的名称、数据类型以及其他约束条件。你可以把它想象成桌子上的一个抽屉,里面放着特定类型的东西(数据)。

在上面的例子中,Column('id', Integer, Identity(), primary_key=True) 就定义了一个名为 id 的列,它的数据类型是整数,并且是主键,自动增长。

5. SQL 表达式:构建 SQL 语句的积木

SQLAlchemy Core 提供了一系列函数,用于构建各种 SQL 语句,例如 select(), insert(), update(), delete() 等。你可以把它们想象成积木,通过组合这些积木,你可以构建出各种复杂的 SQL 语句。

from sqlalchemy import select, insert, update, delete

# 查询所有用户
select_stmt = select(users_table)

# 插入一个新用户
insert_stmt = insert(users_table).values(name='Alice', age=30)

# 更新用户的年龄
update_stmt = update(users_table).where(users_table.c.name == 'Alice').values(age=31)

# 删除用户
delete_stmt = delete(users_table).where(users_table.c.name == 'Alice')

6. Connection:执行 SQL 语句的通道

Connection 对象用于执行 SQL 语句。你可以把它想象成水管,连接水龙头(Engine)和目的地(数据库)。

with engine.connect() as connection:
    # 执行查询语句
    result = connection.execute(select_stmt)
    for row in result:
        print(row)

    # 执行插入语句
    connection.execute(insert_stmt)

    # 执行更新语句
    connection.execute(update_stmt)

    # 执行删除语句
    connection.execute(delete_stmt)

    connection.commit() # 提交事务

第二部分:实战演练:CRUD 操作

现在,让我们通过一个实际的例子来演示如何使用 SQLAlchemy Core 进行 CRUD (Create, Read, Update, Delete) 操作。

1. 创建表

from sqlalchemy import create_engine, MetaData, Table, Column, Integer, String, Identity

engine = create_engine('sqlite:///:memory:')
metadata = MetaData()

users_table = Table(
    'users', metadata,
    Column('id', Integer, Identity(), primary_key=True),
    Column('name', String(50), nullable=False),
    Column('age', Integer)
)

metadata.create_all(engine) # 创建所有表

这里我们创建了一个名为 users 的表,并使用 metadata.create_all(engine) 创建了所有表。

2. 插入数据 (Create)

from sqlalchemy import insert

with engine.connect() as connection:
    insert_stmt = insert(users_table).values([
        {'name': 'Alice', 'age': 30},
        {'name': 'Bob', 'age': 25},
        {'name': 'Charlie', 'age': 35}
    ])
    result = connection.execute(insert_stmt)
    connection.commit()
    print(result.inserted_primary_key) # 打印插入数据的id

这里我们使用 insert() 函数插入了三条数据。

3. 查询数据 (Read)

from sqlalchemy import select

with engine.connect() as connection:
    select_stmt = select(users_table)
    result = connection.execute(select_stmt)
    for row in result:
        print(row)

这里我们使用 select() 函数查询了所有用户,并打印了结果。

from sqlalchemy import select, and_

with engine.connect() as connection:
    select_stmt = select(users_table).where(and_(users_table.c.age > 25, users_table.c.name.like('%li%'))) # 模糊查询包含li的年龄大于25的人
    result = connection.execute(select_stmt)
    for row in result:
        print(row)

这里我们使用 select() 函数查询了年龄大于25,并且名字包含 ‘li’ 的用户,并打印了结果。

4. 更新数据 (Update)

from sqlalchemy import update

with engine.connect() as connection:
    update_stmt = update(users_table).where(users_table.c.name == 'Alice').values(age=31)
    result = connection.execute(update_stmt)
    connection.commit()
    print(result.rowcount) # 打印更新行数

这里我们使用 update() 函数将 Alice 的年龄更新为 31。

5. 删除数据 (Delete)

from sqlalchemy import delete

with engine.connect() as connection:
    delete_stmt = delete(users_table).where(users_table.c.name == 'Bob')
    result = connection.execute(delete_stmt)
    connection.commit()
    print(result.rowcount) # 打印删除行数

这里我们使用 delete() 函数删除了名为 Bob 的用户。

第三部分:高级用法:连接、函数、表达式

SQLAlchemy Core 的强大之处在于它的灵活性和可扩展性。你可以使用它进行各种高级操作,例如连接、函数和复杂表达式。

1. 连接 (Join)

假设我们有两个表:usersaddresses

from sqlalchemy import Table, Column, Integer, String, ForeignKey

addresses_table = Table(
    'addresses', metadata,
    Column('id', Integer, Identity(), primary_key=True),
    Column('user_id', Integer, ForeignKey('users.id')),
    Column('email_address', String(100), nullable=False)
)

metadata.create_all(engine)

现在我们可以使用 join() 函数将这两个表连接起来。

from sqlalchemy import select, join

with engine.connect() as connection:
    join_stmt = select(users_table.c.name, addresses_table.c.email_address).join(addresses_table, users_table.c.id == addresses_table.c.user_id)
    result = connection.execute(join_stmt)
    for row in result:
        print(row)

2. 函数 (Functions)

SQLAlchemy Core 提供了许多内置的函数,例如 func.count(), func.sum(), func.avg() 等。你也可以自定义函数。

from sqlalchemy import func

with engine.connect() as connection:
    count_stmt = select(func.count()).select_from(users_table) # 查询用户数量
    result = connection.execute(count_stmt)
    print(result.scalar()) # 获取单个值

3. 复杂表达式 (Complex Expressions)

你可以使用 Python 的运算符和逻辑运算符来构建复杂的 SQL 表达式。

from sqlalchemy import and_, or_

with engine.connect() as connection:
    select_stmt = select(users_table).where(or_(users_table.c.age > 30, and_(users_table.c.name.like('%A%'), users_table.c.age < 26)))
    result = connection.execute(select_stmt)
    for row in result:
        print(row)

第四部分:事务控制

事务是数据库操作的重要组成部分。SQLAlchemy Core 提供了事务控制的功能,确保数据的一致性和完整性。

with engine.connect() as connection:
    trans = connection.begin() # 开始事务
    try:
        insert_stmt = insert(users_table).values(name='David', age=40)
        connection.execute(insert_stmt)
        update_stmt = update(users_table).where(users_table.c.name == 'Alice').values(age=32)
        connection.execute(update_stmt)
        trans.commit() # 提交事务
    except Exception as e:
        trans.rollback() # 回滚事务
        print(f"发生错误: {e}")

第五部分:绑定参数

为了防止 SQL 注入,你应该使用绑定参数来传递数据。

with engine.connect() as connection:
    select_stmt = select(users_table).where(users_table.c.name == :name)
    result = connection.execute(select_stmt, {"name": "Alice"}) # 使用字典传递参数
    for row in result:
        print(row)

或者:

with engine.connect() as connection:
    select_stmt = select(users_table).where(users_table.c.name == bindparam('name'))
    result = connection.execute(select_stmt, name = "Alice") # 使用bindparam
    for row in result:
        print(row)

第六部分:使用反射读取数据库结构

如果你已经有一个现成的数据库,你可以使用反射功能来读取数据库的结构。

from sqlalchemy import create_engine, MetaData, Table

engine = create_engine('sqlite:///existing_database.db') # 修改为你的数据库
metadata = MetaData()

metadata.reflect(bind=engine) # 反射数据库结构

users_table = metadata.tables['users'] # 获取 users 表

print(users_table.columns.keys()) # 打印 users 表的列名

第七部分:总结与展望

SQLAlchemy Core 是一个强大的工具,它可以让你在 Python 中构建 SQL 表达式,并方便地与各种数据库进行交互。虽然它比 SQLAlchemy ORM 更底层,但它也更加灵活和可控。

特性 SQLAlchemy Core SQLAlchemy ORM
抽象级别
灵活性 较低
学习曲线 陡峭 相对平缓
适用场景 需要精细控制 SQL 语句的复杂应用 简单的 CRUD 操作,快速开发
代码量 较多 较少
数据库抽象 数据库结构抽象,SQL 表达式生成 对象关系映射,数据库表映射到 Python 类
性能 通常更高,因为可以优化 SQL 语句 可能会有性能损耗,取决于 ORM 的使用方式

希望今天的讲座能够帮助你更好地理解 SQLAlchemy Core,并在实际项目中应用它。记住,熟能生巧,多练习才能真正掌握它!

好了,今天的讲座就到这里,谢谢大家! 散会,吃饭去!

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注