跳转至
本文阅读量

1. SQLModel

1.1 定义结构

1.2 插入数据

commit 之后 refresh

session commit 数据已经编辑为过期,如果想要获取最新数据,需要

  • 显示刷新: session.refresh(hero_1)
  • 显示访问对象中的属性: hero_name = hero_1.name, 这个会触发底层执行一次 SQL 获取操作

1.3 查询数据

1.3.1 精确根据主键 id 查询

使用 get()

  • 前提是该字段必须是 primary=True
  • 如果该 id 指定数据不存在,则会抛异常

1.3.2 只查询指定列

[TODO]

1.3.3 一个条件

with Session(engine) as session:
    statement = select(Hero).where(Hero.name == "Spider-Boy")
    hero = session.exec(statement).first()
    print(hero)
session.exec(select(Hero).where(Hero.id == user_id)).all()

1.3.4 多个条件

一个 where 中多个条件

with Session(engine) as session:
    statement = select(Hero).where(Hero.name == "Spider-Boy", Hero.age > 18)
    hero = session.exec(statement).first()
    print(hero)

使用多次 where

with Session(engine) as session:
    statement = select(Hero).where(Hero.name == "Spider-Boy").where(Hero.age > 18)
    hero = session.exec(statement).first()
    print(hero)

1.3.4.1 多个条件但是 or 语义

使用 or_

from sqlmodel import Field, Session, SQLModel, create_engine, or_, select

def select_heroes():
    with Session(engine) as session:
        statement = select(Hero).where(or_(Hero.age <= 35, Hero.age > 90))
        results = session.exec(statement)
        for hero in results:
            print(hero)

1.3.4.2 如何动态生成查询条件

[TODO]

where 中比较用的字段名字要是用类下的字段,而不是实例下的;即要使用大写的 Hero 而不是示例级的 hero

1.3.5 只查询一行

两种方式: result.first()result.one()

数据情况 one() first()
有且仅有一行满足条件的数据 正常返回 正常返回
没有满足条件的数据 抛异常 None
有多条满足条件的数据 抛异常 返回第一条
    statement = select(Hero)
    result = session.exec(statement)
    obj = result.first()

[TODO] 需要看下这里的 first()limit 1 了,还是查会了所有数据,只交给调用方一个,如果是后者,则会有性能问题

1.3.6 指定 offset 和 limit

select() 后增加 limit(n)offset(n)

def select_heroes():
    with Session(engine) as session:
        statement = select(Hero).offset(3).limit(3)
        results = session.exec(statement)
        heroes = results.all()
        print(heroes)

[TODO]

1.4 更新数据

1.5 删除数据

1.5.1 先查后删除

def delete_heroes():
    with Session(engine) as session:
        statement = select(Hero).where(Hero.name == "Spider-Youngster")
        results = session.exec(statement)
        hero = results.one()
        print("Hero: ", hero)

        session.delete(hero)

        session.commit()

1.5.2 直接条件删除

[TODO]

1.6 索引

1.6.1 声明索引

单字段索引

使用 Field(index=True)

class Hero(SQLModel, table=True):
    id: int | None = Field(default=None, primary_key=True)
    name: str = Field(index=True)
    secret_name: str
    age: int | None = Field(default=None, index=True)

复合索引

1.6.1.1 索引声明时指定索引类型

1.6.1.2 索引声明时指定索引名字

1.6.2 索引声明时指定字段顺序

默认 SQLModel(SQLAlchemy) 会自动创建索引名字,规则是


索引声明如何携带额外参数

1.7 关联关系

1.7.1 关系声明

1.7.1.1 1-m/m-1 关系

1.7.1.2 m-n 关系

class HeroTeamLink(SQLModel, table=True):
    team_id: int | None = Field(default=None, foreign_key="team.id", primary_key=True)
    hero_id: int | None = Field(default=None, foreign_key="hero.id", primary_key=True)

class Team(SQLModel, table=True):
    id: int | None = Field(default=None, primary_key=True)
    name: str = Field(index=True)
    headquarters: str

    heroes: list["Hero"] = Relationship(back_populates="teams", link_model=HeroTeamLink)

class Hero(SQLModel, table=True):
    id: int | None = Field(default=None, primary_key=True)
    name: str = Field(index=True)
    secret_name: str
    age: int | None = Field(default=None, index=True)

    teams: list[Team] = Relationship(back_populates="heroes", link_model=HeroTeamLink)

1.7.1.3 声明关系但不用外键

1.7.1.4 关系表的额外字段

class HeroTeamLink(SQLModel, table=True):
    team_id: int | None = Field(default=None, foreign_key="team.id", primary_key=True)
    hero_id: int | None = Field(default=None, foreign_key="hero.id", primary_key=True)
    is_training: bool = False

    team: "Team" = Relationship(back_populates="hero_links")
    hero: "Hero" = Relationship(back_populates="team_links")

1.8 参考