Skip to content

Schema

Schema 即模式,更好的翻译应该是表架构或表元数据。构建 Schema 实际上是 ORM 的核心,他通过面向对象的语句来描述关系型数据库。SQLALchemy 中提供了Schema Definition Language来描述数据库的模式。

组件

SQLAlchemy 为关系型数据库的各个组件提供了对应的类对象:

  • MetaData: 数据库即表(Table)的集合
  • Table: 表
  • Column: 列

这三个对象也是关系型数据库的核心,并且他们是包含关系,即表由列组成,而数据库是表的集合。

MetaData

MetaData是 Table 对象的集合,他是数据库的映射。因此对表的相关操作都是绑定在 MetaData 对象之上的,其中包括创建表、删除表这两个核心操作:

Python
MetaData(
    schema:str=None,  # 定义默认的 schema,默认由 Table 自己指定
    info:dict=None,   # 填充 SchemaItem.info 属性
)

他提供了几个方法用于处理绑定到 MetaData 中的表:

  • create_all(bind:Engine|Connection, tables:list=None, checkfirst=True): 创建由 tables 指定的表(必须绑定到该 MetaData 中),如果 checkfirst 为 True 不对已经存在的表执行创建
  • drop_all(bind:Engine|Connection, tables:list=None, checkfirst=True): 删除 tables 指定的表(必须绑定到该 MetaData 中),如果 checkfirst 为 True 会在删除前先检查
  • reflect(bind:Engine|Connection, schema:str=None, views:bool=True, only:list=None): 反射指定 schema 的由 only 定义的所有表,如果 views 为 True 同时反射视图

他还提供了一个有用的属性 MetaData.tables 来返回绑定到该 MetaData 中的表对象,这在反射后查看表信息很有用。他返回的是 FacadeDict 对象,本质上是 dict 的封装,其中表名为键,表对象为值:

Python
from sqlachemy import create_engine, MetaData

engine = create_engine(url)
metadata = MetaData()
# 反射,结果会保存到 metadata 对象中
metadata.reflect(engine, schema='cnopendata')

# 返回的就是一个类 dict 对象
metadata.tables['student']
Table('student', MetaData(), Column('id', VARCHAR(length=5), table=<student>, primary_key=True, nullable=False), Column('name', VARCHAR(length=20), table=<student>, nullable=False), Column('dept_name', VARCHAR(length=20), ForeignKey('department.dept_name'), table=<student>), Column('tot_cred', NUMERIC(precision=3, scale=0), table=<student>), schema=None)

Table

Table表示数据库中的表:

Python
Table(
    name:str,                   # 表名,注意是区分大小写的即构建 SQL 时会发送引号
    metadata:MetaData,          # 要绑定到的 MetaData 对象即位于的数据库中
    *Columns,                   # 定义列,如果定义了 autoload_with 则可以不定义
    schema:str=None,            # 指定表的 schema,如果为 None 使用 MetaData 中的指定
    comment:str=None,           # 表注释
    autoload_with:Engine=None,  # 用于反射的 engine 或 Connection
    ... # 表级别约束
)

Table 上绑定了一个 Table.columns/Table.c 属性来遍历其中的列:

Python
student = metadata.tables['student']
student.columns
# <sqlalchemy.sql.base.ReadOnlyColumnCollection at 0x7f81a4ad2f20>
student.columns.id
Column('id', VARCHAR(length=5), table=<student>, primary_key=True, nullable=False)

Table 上绑定的方法分为三种类别:

  • 构造 Table 的方法,例如像 Table 中添加 Columns、添加依赖等。这些通常应该在调用 Table 时构建好,相当于后悔药
  • 构建基于 Table 的 SQL 语句,他是构建SQL Statements and Expression Language的基础,例如 Table.select() 这样的方法
  • 还有就是对表的创建、删除等,这个是 schema 应该管理的内容 - create(bind:Engine|Connection, checkfirst=False): 创建表 - drop(bind:Engine|Connection, checkfirst=False): 删除表

Tips

Table 上的创建和删除默认 checkfirst 都是 False,即无论是否表存在都会发送 CREATE 或 DROP 语句,这也是与 MetaData 上不一样的一点。

Column

Column 表示表中的列:

Python
Column(
    name:str,               # 列名称
    type:TypeEngine,        # 列类型
    autoincrement='auto',   # 自增
    default=None,           # 默认值
    doc=None,               # 供 Python 端使用,不是 comment
    comment=None,           # 注释
    index:bool=False,       # 是否自动构造索引
    nullable:bool=True,     # 是否可空
    primary_key:bool=False, # 主键
    unuque:bool=False,      # 唯一
    ... # 其他约束定义
)

Column 是整个 schema 定义的核心,他也是最小组成单元。其中最为核心的就是数据类型以及约束