术语表


1.x 样式

2.0 样式

1.x 样式

2.0 样式


这些术语是 SQLAlchemy 1.4 中的新增功能,指的是 SQLAlchemy 1.4-> 2.0 过渡计划,如 SQLAlchemy 2.0 - 主要迁移指南中所述。 这 术语“1.x 样式”是指按其文档方式使用的 API 贯穿 SQLAlchemy 的 1.x 系列及更早版本(例如 1.3、1.2 等) 术语 “2.0 style” 是指 API 在版本中的外观 2.0. 1.4 版几乎实现了 2.0 的所有 API,即所谓的 “transition mode”,而 2.0 版本仍然保持传统的 Query 对象以允许旧代码在很大程度上保持 2.0 兼容。



ACID 模型


“原子性、一致性、隔离性、持久性”的首字母缩写词;一组保证可靠处理数据库事务的属性。(通过维基百科)


关联关系


一种两层关系,它使用中间的关联表将两个表链接在一起。关联关系从多到多不同 relationship 中映射了多对多表 由一个完整的类处理,而不是由 sqlalchemy.orm.relationship() 结构,以便显式提供其他属性。


例如,如果我们想将员工与项目关联,同时将该员工的特定角色与项目存储在一起,则关系架构可能如下所示:

CREATE TABLE employee (
    id INTEGER PRIMARY KEY,
    name VARCHAR(30)
)

CREATE TABLE project (
    id INTEGER PRIMARY KEY,
    name VARCHAR(30)
)

CREATE TABLE employee_project (
    employee_id INTEGER PRIMARY KEY,
    project_id INTEGER PRIMARY KEY,
    role_name VARCHAR(30),
    FOREIGN KEY employee_id REFERENCES employee(id),
    FOREIGN KEY project_id REFERENCES project(id)
)


上述内容的 SQLAlchemy 声明性映射可能如下所示:

class Employee(Base):
    __tablename__ = "employee"

    id = Column(Integer, primary_key=True)
    name = Column(String(30))


class Project(Base):
    __tablename__ = "project"

    id = Column(Integer, primary_key=True)
    name = Column(String(30))


class EmployeeProject(Base):
    __tablename__ = "employee_project"

    employee_id = Column(Integer, ForeignKey("employee.id"), primary_key=True)
    project_id = Column(Integer, ForeignKey("project.id"), primary_key=True)
    role_name = Column(String(30))

    project = relationship("Project", backref="project_employees")
    employee = relationship("Employee", backref="employee_projects")


可以将员工添加到具有角色名称的项目中:

proj = Project(name="Client A")

emp1 = Employee(name="emp1")
emp2 = Employee(name="emp2")

proj.project_employees.extend(
    [
        EmployeeProject(employee=emp1, role_name="tech lead"),
        EmployeeProject(employee=emp2, role_name="account executive"),
    ]
)


另请参阅


多对多


原子性


原子性是 ACID 模型的组成部分之一,它要求每个事务都是“全有或全无”的:如果事务的一部分失败,则整个事务都会失败,数据库状态保持不变。原子系统必须保证在每种情况下的原子性,包括电源故障、错误和崩溃。(通过维基百科)


已附加


指示当前与特定 会话

backref

双向关系


关系系统的扩展,其中两个不同的 relationship() 对象可以相互关联,以便当任一侧发生更改时,它们在内存中协调。构建这两个关系的最常见方法是为一侧显式使用 relationship() 函数,并为其指定 backref 关键字,以便自动创建另一侧 relationship()。我们可以用 one to many 中使用的示例来说明这一点,如下所示:

class Department(Base):
    __tablename__ = "department"
    id = Column(Integer, primary_key=True)
    name = Column(String(30))
    employees = relationship("Employee", backref="department")


class Employee(Base):
    __tablename__ = "employee"
    id = Column(Integer, primary_key=True)
    name = Column(String(30))
    dep_id = Column(Integer, ForeignKey("department.id"))


backref 可以应用于任何关系,包括 1 对 多、多对 1 和多对多


bound 参数

bound 参数

bind 参数

bind 参数


绑定参数是将数据传递到 DBAPI 数据库驱动程序。虽然要调用的作基于 SQL 语句字符串,但数据值本身是单独传递的,其中驱动程序包含将安全处理这些字符串并将其传递给后端数据库服务器的逻辑,这可能涉及将参数格式化为 SQL 字符串本身,或使用单独的协议将它们传递给数据库。


数据库驱动程序执行此作的特定系统不应 对呼叫者很重要;关键是,从外部来看,数据应该 始终单独传递,而不是作为 SQL 字符串本身的一部分。这对于防止 SQL 注入的足够安全性以及允许驱动程序获得最佳性能都是不可或缺的。


另请参阅


准备好的声明 - 在维基百科上


bind parameters - 在 Use The Index, Luke!


发送参数 - 在 SQLAlchemy Unified 教程


候选键


一个关系代数术语,指的是构成行的唯一标识键的一个属性或一组属性。一行可以有多个候选键,每个候选键都适合用作该行的主键。表的主键始终是候选键。


笛卡尔积


给定两个集合 A 和 B,笛卡尔积是所有有序对 (a, b) 的集合,其中 a 在 A 中,b 在 B 中。


就 SQL 数据库而言,当我们从两个或多个表(或其他子查询)中进行选择时,就会出现笛卡尔积,而没有在一个表的行与另一个表的行之间(直接或间接)建立任何类型的标准。如果我们同时从表 A 和表 B 中 SELECT作,则 A 的每一行都与 B 的第一行匹配,然后 A 的每一行都与 B 的第二行匹配,依此类推,直到 A 中的每一行都与 B 的每一行配对。


笛卡尔积会导致生成大量结果集,如果不加以阻止,很容易使客户端应用程序崩溃。


级联


SQLAlchemy 中使用的一个术语,用于描述对特定对象发生的 ORM 持久性作如何扩展到与该对象直接关联的其他对象。在 SQLAlchemy 中,这些对象关联是使用 relationship() 配置的 构建。 relationship() 包含一个名为 relationship.cascade 中,它提供了有关某些持久化作如何级联的选项。


术语“级联”以及 SQLAlchemy 中该系统的一般架构,无论好坏,都是从 Hibernate ORM 中借来的。


另请参阅


叶 栅


check 约束


检查约束是在关系数据库的表中添加或更新条目时定义有效数据的条件。检查约束将应用于表中的每一行。


(通过维基百科)


可以使用 DDL 将 check 约束添加到标准 SQL 中的表中,如下所示:

ALTER TABLE distributors ADD CONSTRAINT zipchk CHECK (char_length(zipcode) = 5);

columns 子句


SELECT 语句中枚举要在结果集中返回的 SQL 表达式的部分。表达式直接跟在 SELECT 关键字后面,并且是各个表达式的逗号分隔列表。


例如:

SELECT user_account.name, user_account.email
FROM user_account WHERE user_account.name = 'fred'


上面是列列表 user_acount.nameuser_account.emailSELECT 的 columns 子句。


复合主键


具有多个列的主。特定的数据库行基于两个或多个列是唯一的,而不仅仅是一个值。


另请参阅


主键


一致性


一致性是 ACID 模型的组成部分之一,它确保任何事务都会将数据库从一个有效状态带到另一个有效状态。写入数据库的任何数据都必须根据所有定义的规则有效,包括但不限于约束、级联、触发器及其任意组合。(通过维基百科)


约束

约束

受约束


在关系数据库中建立的规则,用于确保数据的有效性和一致性。约束的常见形式包括 primary key constraint外键约束CHECK 约束


correlates(关联)¶

关联子查询

关联子查询


如果子查询依赖于封闭 SELECT 中的数据,则子查询是相关的。


下面,子查询选择聚合值 MIN(a.id)email_address 表中,以便为 user_account.id 的每个值调用它,并将此列的值与 email_address.user_account_id 相关联 列:

SELECT user_account.name, email_address.email
 FROM user_account
 JOIN email_address ON user_account.id=email_address.user_account_id
 WHERE email_address.id = (
    SELECT MIN(a.id) FROM email_address AS a
    WHERE a.user_account_id=user_account.id
 )


上面的子查询引用了 user_account 表,它本身并不在此嵌套查询的 FROM 子句中。相反,user_account table 从封闭查询中接收,其中每行都从 user_account会导致子查询的不同执行。


在大多数情况下,相关子查询存在于 WHERE 子句中 或 columns 子句 语句,以及 ORDER BY 或 HAVING 子句。


在不太常见的情况下,相关子查询可能存在于 封闭 SELECTFROM 子句;在这些情况下,相关性通常是由于封闭的 SELECT 本身包含在另一个 SELECT 的 WHERE、ORDER BY、列或 HAVING 子句中,例如:

SELECT parent.id FROM parent
WHERE EXISTS (
    SELECT * FROM (
        SELECT child.id AS id, child.parent_id AS parent_id, child.pos AS pos
        FROM child
        WHERE child.parent_id = parent.id ORDER BY child.pos
    LIMIT 3)
WHERE id = 7)


从一个 SELECT 直接关联到一个通过其 FROM 包含相关查询的 SELECT 子句,因为关联只能在 封闭语句的 FROM 子句中的原始源行可用。

crud

CRUD 浏览器¶


首字母缩略词,意思是“创建、更新、删除”。SQL 中的术语是指从数据库创建、修改和删除数据的一组作,也称为 DML,通常是指 INSERT。 UPDATEDELETE 语句。


光标


一种控制结构,用于遍历数据库中的记录。在 Python DBAPI 中,游标对象实际上是语句执行的起点,也是用于获取结果的接口。


圈复杂度


根据程序源代码的可能路径数来衡量代码复杂性。


另请参阅


圈复杂度


数据库接口

PEP-249 的兼容性¶


DBAPI 是短语“Python 数据库 API 规格”。 这是一个广泛使用的规范 来定义所有 数据库连接包。 DBAPI 是“低级别” API 通常是使用的最低级别系统 在 Python 应用程序中与数据库通信。 SQLAlchemy 的 dialect System 是围绕 DBAPI 的作构建的,提供单独的 dialect 类,这些类在特定的数据库引擎之上为特定的 DBAPI 提供服务;例如,create_engine() 网址 postgresql+psycopg2://@localhost/test 指的是 psycopg2 DBAPI/dialect 组合,而 URL mysql+mysqldb://@localhost/testMySQL for Python DBAPI/方言组合。


DDL (DDL) ¶


Data Definition Language 的首字母缩写词。DDL 是关系数据库用于配置数据库架构中的表、约束和其他永久对象的 SQL 子集。SQLAlchemy 提供了丰富的 API 来构造和发出 DDL 表达式。


已删除


这描述了一个对象在 Session 中可以具有的主要对象状态之一;已删除的对象是以前是持久性的对象,并且在 flush 中向数据库发出了 DELETE 语句以删除其行。对象将移动到已分离的 state 的 state 的 Deal 提交后;或者 如果会话的事务回滚,则 DELETE 为 reverted 的 Related 对象将移回持久 州。


描述符

描述符


在 Python 中,描述器是具有“绑定行为”的对象属性, 其属性访问已被 Descriptor 协议。这些方法是 __get__()、__set__()__delete__()。如果为对象定义了这些方法中的任何一个,则称其为描述符。


在 SQLAlchemy 中,大量使用描述符来提供 Map 类的属性行为。当类按如下方式映射时:

class MyClass(Base):
    __tablename__ = "foo"

    id = Column(Integer, primary_key=True)
    data = Column(String)


MyClass 类的定义完成后,将映射该类,此时 iddata 属性(从 Column 对象开始)将替换为具有 InstrumentedAttribute 实例的插桩系统,这些实例是提供上述 __get__()、__set__() 的描述符__delete__() 方法。InstrumentedAttribute 在类级别使用时将生成一个 SQL 表达式:

>>> print(MyClass.data == 5)
data = :data_1


在实例级别,跟踪对 values 的更改,并从数据库中延迟加载 unloaded 的属性:

>>> m1 = MyClass()
>>> m1.id = 5
>>> m1.data = "some data"

>>> from sqlalchemy import inspect
>>> inspect(m1).attrs.data.history.added
"some data"

detached(分离)¶


这描述了一个对象在 Session 中可以具有的主要对象状态之一;分离的对象是具有数据库标识(即主键)但不与任何会话关联的对象。先前是持久性对象,并且由于被清除或拥有会话已关闭而从其会话中删除的对象将进入 detached 状态。当对象在会话之间移动或移入/移出外部对象高速缓存时,通常使用 detached 状态。


方言


在 SQLAlchemy 中,“dialect” 是表示信息的 Python 对象 以及允许数据库作对特定 类型的数据库后端和特定类型的 Python 驱动程序(或 DBAPI)对于该数据库。SQLAlchemy 方言是 Dialect 类的子类。


另请参阅


引擎配置


判别器


多态加载期间使用的结果集列,用于确定应将哪种映射类应用于特定的传入结果行。


DML (DML) ¶


Data Manipulation Language 的首字母缩写词。DML 是关系数据库用于修改表中数据的 SQL 子集。DML 通常是指 INSERT、UPDATE 和 DELETE 这三个广为人知的语句,也称为 CRUD(“Create, Read, Update, Delete”的首字母缩写词)。


domain model(域模型)¶


问题解决和软件工程中的领域模型是与特定问题相关的所有主题的概念模型。它描述了各种实体、它们的属性、角色和关系,以及控制问题域的约束。


(通过维基百科)

DQL


Data Query Language 的首字母缩写词。DQL 是关系数据库用于读取表中数据的 SQL 子集。DQL 几乎完全将 SQL SELECT 构造称为正在使用的顶级 SQL 语句。


耐久性¶


持久性是 ACID 模型的一个属性,这意味着一旦提交了事务,即使在断电、崩溃或错误的情况下,它也会保持这种状态。例如,在关系数据库中,一旦执行了一组 SQL 语句,结果就需要永久存储(即使数据库在此后立即崩溃)。(通过维基百科)


急切加载

Eager 加载

eager loaded 已加载)

预先加载

预先加载


在对象关系映射中,“预先加载”是指一个属性 ,该值会填充其数据库端值,同时在 对象本身是从数据库中加载的。在 SQLAlchemy 中,术语 “eager loading” 通常是指 使用 relationship() 结构,但也可以引用其他 column 属性,通常来自与 正在查询的特定表,例如使用 继承映射。


预先加载与延迟加载相反。


另请参阅


关系加载技术

executemany


该术语是指 PEP 249 DBAPI 规范的一部分 指示可针对 具有多个参数集的数据库连接。 特定的 method 称为 cursor.executemany()中, 与 cursor.execute() 方法,用于单语句调用。 “executemany” 方法多次执行给定的 SQL 语句,一次用于 传递的每组参数。 使用 executeMany 是性能改进的 PRESENT,其中 DBAPI 可以 使用诸如事先准备一次语句等技术, 或者优化多次调用同一语句。


当在传递参数字典列表时使用 Connection.execute() 方法时,SQLAlchemy 通常会自动使用 cursor.executemany() 方法;这向 SQLAlchemy Core 表明 SQL 语句和处理的参数集应该传递给 cursor.executemany(),其中该语句将由驱动程序为每个参数字典单独调用。


与所有已知 DBAPI 一起使用的 cursor.executemany() 方法的一个关键限制是,使用此方法时,游标未配置为返回行。对于大多数后端(一个值得注意的例外是 python-oracledb / cx_Oracle DBAPI),这意味着像 INSERT..RETURNING 通常不能与 cursor.executemany() 直接聚合,因为 DBAPI 通常不会将每个 INSERT 执行中的单行聚合在一起。


为了克服这个限制,SQLAlchemy 从 2.0 系列开始实现了 “executemany” 的另一种形式,称为 INSERT 语句的 “Insert many values” 行为。此功能利用 cursor.execute() 来调用 INSERT 语句,该语句将在一次往返中处理多个参数集,从而产生与使用 cursor.executemany() 相同的效果,同时仍然支持 RETURNING。


另请参阅


发送多个参数 - “executemany” 教程介绍


INSERT 语句的 “Insert Many Values” 行为 - 允许将 RETURNING 与 “executemany” 一起使用的 SQLAlchemy 功能


过期

过期

过期

过期

过期


在 SQLAlchemy ORM 中,指的是当持久化 或者有时 detached 对象会被擦除,这样当下次访问对象的属性时,将发出延迟加载 SQL 查询,以刷新存储在当前正在进行的事务中的此对象的数据。


另请参阅


刷新 / 过期


门面


一个对象,用作掩盖更复杂的底层或结构代码的正面接口。


flush 刷新¶

刷新

flushed(刷新)


这是指工作单元使用的实际流程 以发出对数据库的更改。 在 SQLAlchemy 中,此过程发生 通过 Session 对象,通常是自动的,但也可以手动控制。


另请参阅


冲洗


外键约束


两个表之间的引用约束。外键是关系表中与另一个表的候选键匹配的一个字段或一组字段。外键可用于交叉引用表。(通过维基百科)


可以使用 DDL 将外键约束添加到标准 SQL 中的表中,如下所示:

ALTER TABLE employee ADD CONSTRAINT dep_id_fk
FOREIGN KEY (employee) REFERENCES department (dep_id)

FROM 子句


SELECT 语句中指示行的初始源的部分。


简单的 SELECT 将在其 FROM 子句中包含一个或多个表名。多个源之间用逗号分隔:

SELECT user.name, address.email_address
FROM user, address
WHERE user.id=address.user_id


FROM 子句也是指定显式联接的地方。我们可以使用单个 FROM 元素重写上述 SELECT,该元素由两个表的 JOIN 组成:

SELECT user.name, address.email_address
FROM user JOIN address ON user.id=address.user_id

身份密钥


与 ORM 映射对象关联的键,用于标识它们在数据库中的主键身份,以及它们在 Session身份映射中的唯一身份。


在 SQLAlchemy 中,您可以使用 inspect() API 查看 ORM 对象的标识键,以返回 InstanceState 跟踪对象,然后查看 InstanceState.key 属性:

>>> from sqlalchemy import inspect
>>> inspect(some_object).key
(<class '__main__.MyTable'>, (1,), None)


另请参阅


身份映射


身份映射


Python 对象与其数据库身份之间的映射。身份映射是一个与 ORM Session 对象关联的集合,并维护每个数据库对象的单个实例,该实例以其身份为键。此模式的优点是,针对特定数据库身份发生的所有作都透明地协调到单个对象实例上。当将身份映射与隔离事务结合使用时,从实际角度来看,可以认为对已知具有特定主键的对象的引用是实际数据库行的代理。


另请参阅


身份地图(通过 Martin Fowler)


按主键获取 - 如何按主键在身份映射中查找对象


命令式¶

声明式


在 SQLAlchemy ORM 中,这些术语指的是将 Python 类映射到数据库表的两种不同样式。


insertmany值


这是指特定于 SQLAlchemy 的功能,该功能允许 INSERT 语句在单个语句中发出数千个新行,同时允许使用 RETURNING 或类似方法从语句内联返回服务器生成的值,以达到性能优化目的。该功能旨在透明地用于选定的后端,但确实提供了一些配置选项。有关此功能的完整说明,请参阅 INSERT 语句的“插入多个值”行为部分。


插桩

插桩

插桩


插桩是指扩充特定类的功能和属性集的过程。理想情况下,类的行为应保持接近常规类,但其他行为和功能可用。SQLAlchemy 映射过程除其他外,还添加了启用数据库的描述符 映射到映射的 类,每个类都表示一个特定的数据库列 或与相关类的关系。


隔离

isolated(隔离)¶

隔离级别


ACID 模型的隔离属性确保事务的并发执行会产生一种系统状态,如果事务是按顺序执行的,即一个接一个地执行,则会获得该状态。每个事务都必须完全隔离执行,即如果 T1 和 T2 同时执行,则每个事务都应保持独立于另一个事务。(通过维基百科)


懒惰初始化


一种延迟某些初始化作(例如创建对象、填充数据或建立与其他服务的连接)直到需要这些资源的策略。


延迟加载

延迟加载

延迟加载

延迟加载


在对象关系映射中,“延迟加载”是指 不包含其数据库端值的属性 一段时间内,通常当对象为 首次加载。 相反,该属性会收到一个 memoization 的调用,这会导致它在第一次使用时进入数据库并加载其数据。使用这种模式,有时可以减少对象获取的复杂性和花费的时间,因为相关表的属性不需要立即解决。


延迟加载与预先加载相反。


在 SQLAlchemy 中,延迟加载是 ORM 的一个关键功能,适用于映射在用户定义类上的属性。当访问引用数据库列或相关对象的属性时,如果不存在 loaded 值,则 ORM 使用与当前对象关联的持久状态的 Session,并在当前事务上发出 SELECT 语句,如果新事务未进行,则启动新事务。如果对象位于 detached state 中,并且不与任何 Session 关联,则为 被视为 Error 状态,并且 informative 异常


另请参阅


延迟加载(通过 Martin Fowler)


N 加 1 问题


列加载选项 - 包括有关 ORM 映射列的延迟加载的信息


关系加载技术 - 包括有关 ORM 相关对象的延迟加载的信息


使用 AsyncSession 时防止隐式 IO - 使用异步 I/O (asyncio) 扩展时避免延迟加载的提示


多对多


一种 sqlalchemy.orm.relationship() 样式,它通过中间的中间表将两个表链接在一起。使用此配置,左侧的任意数量的行都可以引用右侧的任意数量的行,反之亦然。


员工可与项目关联的架构:

CREATE TABLE employee (
    id INTEGER PRIMARY KEY,
    name VARCHAR(30)
)

CREATE TABLE project (
    id INTEGER PRIMARY KEY,
    name VARCHAR(30)
)

CREATE TABLE employee_project (
    employee_id INTEGER PRIMARY KEY,
    project_id INTEGER PRIMARY KEY,
    FOREIGN KEY employee_id REFERENCES employee(id),
    FOREIGN KEY project_id REFERENCES project(id)
)


在上面,employee_project表是多对多表,它自然会形成一个复合主键,由每个相关表中的主键组成。


在 SQLAlchemy 中,sqlalchemy.orm.relationship() 函数可以以几乎透明的方式表示这种关系样式,其中多对多表是使用普通表元数据指定的:

class Employee(Base):
    __tablename__ = "employee"

    id = Column(Integer, primary_key=True)
    name = Column(String(30))

    projects = relationship(
        "Project",
        secondary=Table(
            "employee_project",
            Base.metadata,
            Column("employee_id", Integer, ForeignKey("employee.id"), primary_key=True),
            Column("project_id", Integer, ForeignKey("project.id"), primary_key=True),
        ),
        backref="employees",
    )


class Project(Base):
    __tablename__ = "project"

    id = Column(Integer, primary_key=True)
    name = Column(String(30))


上图为 Employee.projects 和反向引用 Project.employees 集合定义如下:

proj = Project(name="Client A")

emp1 = Employee(name="emp1")
emp2 = Employee(name="emp2")

proj.employees.extend([emp1, emp2])

多对一


一种 relationship() 样式,它将父映射器表中的外键链接到相关表的主键。然后,每个父对象可以恰好引用零个或一个相关对象。


反过来,相关对象将与引用它们的任意数量的父对象具有隐式或显式的一对多关系。


一个多对一架构示例(请注意,它与一对多架构相同):

CREATE TABLE department (
    id INTEGER PRIMARY KEY,
    name VARCHAR(30)
)

CREATE TABLE employee (
    id INTEGER PRIMARY KEY,
    name VARCHAR(30),
    dep_id INTEGER REFERENCES department(id)
)


员工部门之间的关系是多对一的,因为许多员工记录可以与单个部门关联。SQLAlchemy 映射可能如下所示:

class Department(Base):
    __tablename__ = "department"
    id = Column(Integer, primary_key=True)
    name = Column(String(30))


class Employee(Base):
    __tablename__ = "employee"
    id = Column(Integer, primary_key=True)
    name = Column(String(30))
    dep_id = Column(Integer, ForeignKey("department.id"))
    department = relationship("Department")

映射

映射

mapped 类

ORM 映射类


当一个类与 Mapper 类的实例相关联时,我们说它被 “映射” 了。此过程将类与数据库表或其他可选结构 以便可以使用 会话


另请参阅


ORM 映射类概述


编组

数据编组


当数据必须在计算机程序的不同部分之间或从一个程序移动到另一个程序时,将对象的内存表示转换为适合存储或传输到系统另一部分的数据格式的过程。就 SQLAlchemy 而言,我们经常需要将数据 “编组” 为适合传递到关系数据库的格式。


另请参阅


编组(通过 Wikipedia)


扩充现有类型 - SQLAlchemy 的 TypeDecorator 通常用于数据封送,因为数据被发送到 database 的 INSERT 和 UPDATE 语句,以及 “unmarshalling” data 时,它是使用 SELECT 语句检索的。


元数据

数据库元数据

表元数据


术语“元数据”通常是指“描述数据的数据”;data 本身表示某些其他类型数据的格式和/或结构。在 SQLAlchemy 中,术语“元数据”通常是指 MetaData 结构,它是有关特定数据库中可能存在的表、列、约束和其他 DDL 对象的信息集合。


方法链接

生成


“方法链接”在 SQLAlchemy 文档中称为“生成式”,是一种面向对象的技术,通过调用对象上的方法来构造对象的状态。该对象具有任意数量的方法,每个方法都返回一个新对象(或在某些情况下是相同的对象),并向对象添加了额外的状态。


最充分利用方法链接的两个 SQLAlchemy 对象是 Select object 和 Query 对象。例如,通过调用 Select.where(),可以为 Select 对象的 WHERE 子句分配两个表达式,并为 ORDER BY 子句分配两个表达式 和 Select.order_by() 方法:

stmt = (
    select(user.c.name)
    .where(user.c.id > 5)
    .where(user.c.name.like("e%"))
    .order_by(user.c.name)
)


上面的每个方法调用都会返回原始 选择添加了其他限定符的对象。


mixin 类

mixin 类


一种常见的面向对象的模式,其中的类包含供其他类使用的方法或属性,而不必是其他类的父类。


N 加 1 个问题

N 加 1


N 加 1 问题是 延迟加载模式,应用程序希望遍历对象结果集的每个成员上的相关属性或集合,其中该属性或集合设置为通过延迟加载模式加载。最终结果是发出 SELECT 语句以加载父对象的初始结果集;然后,当应用程序遍历每个成员时,将为每个成员发出一个额外的 SELECT 语句,以便加载该成员的相关属性或集合。最终结果是,对于包含 N 个父对象的结果集,将发出 N + 1 个 SELECT 语句。


使用 Eager loading 缓解了 N 加 1 问题。


一对多


一种 relationship() 样式,它将父映射器表的主键链接到相关表的外键。然后,每个唯一的父对象可以引用零个或多个唯一的相关对象。


反过来,相关对象将与其父对象具有隐式或显式的多对一关系。


一个示例:一对多架构(请注意,它与多对一架构相同):

CREATE TABLE department (
    id INTEGER PRIMARY KEY,
    name VARCHAR(30)
)

CREATE TABLE employee (
    id INTEGER PRIMARY KEY,
    name VARCHAR(30),
    dep_id INTEGER REFERENCES department(id)
)


从部门员工的关系是一对多的,因为许多员工记录可以与单个部门相关联。SQLAlchemy 映射可能如下所示:

class Department(Base):
    __tablename__ = "department"
    id = Column(Integer, primary_key=True)
    name = Column(String(30))
    employees = relationship("Employee")


class Employee(Base):
    __tablename__ = "employee"
    id = Column(Integer, primary_key=True)
    name = Column(String(30))
    dep_id = Column(Integer, ForeignKey("department.id"))

ORM 注解

注解


短语“ORM 注释”指的是 SQLAlchemy 的一个内部方面,其中 Core 对象(如 Column 对象)可以携带额外的运行时信息,将其标记为属于特定的 ORM 映射。该术语不应与常用短语“类型注释”混淆,后者指的是 PEP 484 中介绍的用于静态类型的 Python 源代码“类型提示”。


SQLAlchemy 的大多数记录代码示例都带有关于“Annotated Example”或“Non-annotated Example”的小注释。这是指该示例是否带有 PEP 484 注释,并且与“ORM 注释”的 SQLAlchemy 概念无关。


当短语“ORM-annotated”出现在文档中时,它指的是核心 SQL 表达式对象,例如 TableColumnSelect 对象,它们源自或引用源自一个或多个 ORM 映射的子元素,因此在传递给 ORM 方法(如 Session.execute())时,将具有特定于 ORM 的解释和/或行为。例如,当我们从 ORM 映射构造一个 Select 对象时,例如 ORM 教程

>>> stmt = select(User)


上述 Select 的内部状态是指 User 映射到的。不会立即引用 User 类本身。这就是 Select construct 与 Core 级别的进程保持兼容(请注意, Select._raw_columns 成员是私有的,不应由最终用户代码访问):

>>> stmt._raw_columns
[Table('user_account', MetaData(), Column('id', Integer(), ...)]


但是,当我们的 Select 被传递给 ORM 时 Session 中,与对象间接关联的 ORM 实体用于在 ORM 上下文中解释此 Select。实际的 “ORM 注解” 可以在另一个私有变量中看到 ._annotations

>>> stmt._raw_columns[0]._annotations
immutabledict({
  'entity_namespace': <Mapper at 0x7f4dd8098c10; User>,
  'parententity': <Mapper at 0x7f4dd8098c10; User>,
  'parentmapper': <Mapper at 0x7f4dd8098c10; User>
})


因此,我们将 stmt 称为 ORM 注释的 select() 对象。它是一个 Select 语句,其中包含额外的信息,当传递给 Session.execute() 等方法时,将导致它以特定于 ORM 的方式被解释。


待处理


这描述了一个对象在 Session 中可以具有的主要对象状态之一;待处理对象是没有任何数据库标识但最近已与会话关联的新对象。当会话发出 flush 并插入行时,对象将移动到持久状态。


持久化¶


这描述了一个对象在 Session 中可以具有的主要对象状态之一;持久对象是具有数据库标识(即主键)且当前与 Session 关联的对象。以前待处理但现在已插入的任何对象都处于持久状态,会话从数据库加载的任何对象也是如此。从会话中删除持久性对象时,它称为 detached


插件

启用插件

插件特定


“plugin-enabled” 或 “plugin-specific” 通常表示 SQLAlchemy Core 中的函数或方法,在 ORM 上下文中使用时,其行为会有所不同。


SQLAlchemy 允许 Select 对象等 Core 结构参与“插件”系统,该系统可以将默认情况下不存在的其他行为和功能注入对象中。


具体来说,主要的“插件”是“orm”插件,它是 SQLAlchemy ORM 利用 Core 结构来编写和执行返回 ORM 结果的 SQL 查询的系统基础。


多态

多态


指一次处理多个类型的函数。在 SQLAlchemy 中,该术语通常应用于 ORM 映射类的概念,其中查询作将根据结果集中的信息返回不同的子类,通常是通过检查结果中称为鉴别器的特定列的值。


SQLAlchemy 中的多态加载意味着 one 或 a 三种不同方案的组合用于映射层次结构 的类;“joined”、“single” 和 “concrete”。 该部分 映射类继承层次结构 全面介绍了继承映射。


主键

主键约束


唯一定义表中每一行特征的约束。主键必须包含不能被任何其他行复制的特征。主键可以由单个属性或多个属性组合组成。(通过维基百科)


表的主键通常在 CREATE TABLEDDL 中定义,但并非总是如此:

CREATE TABLE employee (
     emp_id INTEGER,
     emp_name VARCHAR(30),
     dep_id INTEGER,
     PRIMARY KEY (emp_id)
)

读取已提交


四个数据库隔离级别之一,读提交功能使事务不会暴露给来自其他尚未提交的并发事务的任何数据,从而防止所谓的“脏读”。但是,在 read committed 下,可能存在不可重复的读取,这意味着如果另一个事务已提交更改,则行中的数据在第二次读取时可能会更改。


读取未提交


读取未提交功能是四个数据库隔离级别之一,即在提交事务之前,对事务中的数据库数据所做的更改不会成为永久性的。但是,在 read uncommitted 中,未在其他事务中提交的数据有可能在另一个事务的范围内可见;这些被称为 “脏读”。


反射

reflected(反射型)


在 SQLAlchemy 中,该术语是指查询数据库的架构目录以加载有关现有表、列、约束和其他构造的信息的功能。SQLAlchemy 包含的功能既可以为此信息提供原始数据,也可以自动从数据库架构目录构建 Core/ORM 可用的 Table 对象。


另请参阅


Reflecting Database Objects - 数据库反射的完整背景。


Mapping Declarativeically with Reflected Tables - 将 ORM 映射与反射表集成的背景。


注册表


一个对象,通常全局可访问,其中包含有关某些程序状态的长期信息,这些信息通常对程序的许多部分有用。


关系

关系代数


由 Edgar F. Codd 开发的代数系统,用于对关系数据库中存储的数据进行建模和查询。


关系

关系


两个映射类之间的连接单元,对应于数据库中两个表之间的某种关系。


该关系是使用 SQLAlchemy 函数定义的 relationship() 的 创建后,SQLAlchemy 检查涉及的参数和底层映射 为了将关系分类为以下三种类型之一: 一对多多对一多对多。通过此分类,关系构造可以处理在数据库中保留适当链接以响应内存中对象关联的任务,以及根据数据库中的当前链接将对象引用和集合加载到内存中的任务。


另请参阅


关系配置


发布

版本

已发布


在 SQLAlchemy 的上下文中,术语 “released” 是指结束使用特定数据库连接的过程。SQLAlchemy 的特点是使用连接池,这允许对数据库连接的生命周期进行配置。当使用池化连接时,“关闭”它的过程,即调用像 connection.close() 这样的语句,可能会产生 将连接返回到现有池, 或者它可能具有实际关闭 该连接引用的基础 TCP/IP 连接 - 发生哪一个也取决于配置 作为池的当前状态。 所以我们使用了 相反,发布为“当我们用完连接后,做你对连接所做的任何事情”。


该术语有时会用于短语 “release transactional resources” 中,以更明确地表示我们实际上 “releaseing” 的是连接时积累的任何事务状态。在大多数情况下,从 table 中进行选择、发出更新等的过程会在该连接上获取隔离状态以及潜在的行或表锁。此状态对于连接上的特定事务都是本地的,并在我们发出回滚时释放。连接池的一个重要特性是,当我们将连接返回到池中时,connection.rollback() 方法,因此,由于 连接设置为再次使用,它处于 “干净” 状态 状态,没有对上一个序列的引用 的作。


另请参阅


连接池


可重复读取


作为四个数据库隔离级别之一,可重复读取具有所有已提交读取的隔离,并且还具有从该点开始保证在事务中读取的任何特定行在该事务的持续时间内没有任何后续的外部值更改(即来自其他并发 UPDATE 语句)。


返回


这是某些后端以各种形式提供的非 SQL 标准子句,它提供在执行 INSERT、UPDATE 或 DELETE 语句时返回结果集的服务。可以返回匹配行中的任何列集,就像它们是从 SELECT 语句生成的一样。


RETURNING子句既为常见的更新/选择场景提供了显著的性能提升,包括在创建内联或默认生成的主键值和默认值时检索它们,也提供了一种以原子方式获取服务器生成的默认值的方法。


PostgreSQL 惯用的 RETURNING 示例如下所示:

INSERT INTO user_account (name) VALUES ('new name') RETURNING id, timestamp


上面,INSERT 语句将在执行时提供一个结果集,其中包括列 user_account.iduser_account.timestamp,上面应该生成为默认值,因为它们不包括在内(但请注意,任何系列的列或 SQL 表达式都可以放入 RETURNING 中,而不仅仅是默认值列)。


当前支持 RETURNING 或类似构造的后端是 PostgreSQL、SQL Server、Oracle Database 和 Firebird。PostgreSQL 和 Firebird 实现通常是功能齐全的,而 SQL Server 和 Oracle Database 的实现则有注意事项。在 SQL Server 上,对于 INSERT 和 UPDATE 语句,该子句称为“OUTPUT INSERTED”,对于 DELETE 语句,该子句称为“OUTPUT DELETED”;需要注意的是,不支持将 triggers 与此关键字结合使用。在 Oracle 数据库中,它被称为 “RETURNING...INTO“,并要求将值放入 OUT 参数中,这意味着不仅语法笨拙,而且一次只能用于一行。


SQLAlchemy 的 UpdateBase.returning() 系统在这些后端的 RETURNING 系统之上提供了一个抽象层,为返回列提供了一个一致的接口。ORM 还包括许多优化,这些优化在可用时使用 RETURNING。


可选


SQLAlchemy 中使用的一个术语,用于描述表示行集合的 SQL 构造。它与关系代数中的 “relation” 概念基本相似。在 SQLAlchemy 中,当使用 SQLAlchemy Core 时,子类化 Selectable 类的对象被视为可用作“可选对象”。两种最常见的结构是 Table 的结构和 Select 语句。


哨兵

插入 Sentinel


这是一个特定于 SQLAlchemy 的术语,指的是 可用于批量的 insertmanyvalues作来跟踪 INSERTed 数据记录 针对使用 RETURNING 或类似方式传回的行。 这样的 列配置是必需的,因为 insertmanyvalues 功能执行优化的 INSERT..RETURNING 语句,同时仍然能够保证返回的行的顺序与输入数据匹配。


对于典型用例,SQLAlchemy SQL 编译器可以自动 使用代理整数主键列作为 “INSERT sentinels“,并且不需要用户配置。 对于不太常见的 case 替换为其他种类的服务器生成的主键值, 可以选择在 table 元数据,以优化一次插入多行的 INSERT 语句。


可序列化


作为四个数据库隔离级别之一,可序列化具有可重复读取的所有隔离,此外,在基于锁的方法中保证了所谓的“幻读”不会发生;这意味着在其他事务范围内 INSERTed 或 DELETEd 的行将无法在此事务中检测到。保证在此事务中读取的行继续存在,而不存在的行保证它不会显示为从另一个事务插入的行。


可序列化隔离通常依赖于锁定行或行范围才能实现此效果,并且会增加死锁的可能性并降低性能。还有一些非基于锁的方案,但是如果检测到写入冲突,这些方案必然依赖于拒绝事务。


会话


ORM 数据库作的容器或范围。会话从数据库中加载实例,跟踪对映射实例的更改,并在刷新时将更改保存在单个工作单元中。


另请参阅


使用会话


子查询

标量子查询


引用嵌入在封闭中的 SELECT 语句 选择。


子查询有两种一般形式,一种称为“标量选择”,它明确必须只返回一行和一列,另一种形式充当“派生表”并用作另一个选择的 FROM 子句的行源。标量选择可以放置在封闭选择中的 WHERE 子句columns 子句、ORDER BY 子句或 HAVING 子句中,而派生表形式可以放置在封闭 SELECT 的 FROM 子句中。


例子:


  1. 放置在封闭的 columns 子句中的标量子查询 选择。此示例中的 subquery 是相关子查询,因为它从中选择的部分行是通过 enclosing 语句给出的。

    SELECT id, (SELECT name FROM address WHERE address.user_id=user.id)
    FROM user

  2. 放置在封闭的 WHERE 子句中的标量子查询 选择。此示例中的此子查询不相关,因为它选择固定结果。

    SELECT id, name FROM user
    WHERE status=(SELECT status_id FROM status_code WHERE code='C')

  3. 放置在封闭的 FROM 子句中的派生表子查询 选择。这样的子查询几乎总是被赋予别名。

    SELECT user.id, user.name, ad_subq.email_address
    FROM
        user JOIN
        (select user_id, email_address FROM address WHERE address_type='Q') AS ad_subq
        ON user.id = ad_subq.user_id

瞬态


这描述了一个对象在 Session 中可以具有的主要对象状态之一;瞬态对象 是没有任何数据库标识的新对象 ,并且尚未与会话关联。 当 对象添加到 Session 中,它会移动到 pending 状态。


unique 约束

唯一键索引


唯一键索引可以唯一标识数据库表中的每一行数据值。唯一键索引由单个数据库表中的单个列或一组列组成。如果未使用 NULL 值,则数据库表中没有两个不同的行或数据记录可以在这些唯一键索引列中具有相同的数据值(或数据值的组合)。根据其设计,数据库表可能具有许多唯一键索引,但最多只有一个主键索引。


(通过维基百科)


工作单元


一种软件体系结构,其中持久性系统(如对象关系映射器)维护对一系列对象所做的更改列表,并定期将所有这些待处理的更改刷新到数据库中。


SQLAlchemy 的 Session 实现了工作单元模式,其中使用 Session.add() 等方法添加到 Session 的对象将参与工作单元风格的持久化。


有关 SQLAlchemy 中工作单元持久性的演练,请从使用 ORM 进行数据作部分开始 在 SQLAlchemy Unified Tutorial 中。 然后,有关更多详细信息,请参阅 一般参考文档中的 Basics of Using a Session 中的。


版本 ID 列


在 SQLAlchemy 中,这是指使用特定的 table 列,当行更改值时,该列跟踪特定行的 “version” 。虽然有不同种类的关系模式以不同的方式使用“版本 ID 列”,但 SQLAlchemy 的 ORM 包括一个特殊功能,该功能允许配置这样的列,以便在使用新信息更新行时测试过时的数据。如果当我们尝试将新数据放入该行时,此列的最后一个已知 “版本” 与该行的 “版本” 不匹配,则我们知道我们正在处理过时的信息。


还有其他方法可以在数据库中存储 “versioned” 行,通常称为 “temporal” 数据。除了 SQLAlchemy 的版本控制功能外,文档中还提供了更多示例,请参阅下面的链接。


另请参阅


配置版本计数器 - SQLAlchemy 的内置版本 ID 功能。


版本控制对象 - 临时对行进行版本控制的映射的其他示例。


WHERE 子句


SELECT 语句的一部分,指示应作为筛选行的条件。它是跟在关键字 WHERE 后面的单个 SQL 表达式。

SELECT user_account.name, user_account.email
FROM user_account
WHERE user_account.name = 'fred' AND user_account.status = 'E'


在上面,短语 WHERE user_account.name = 'fred' AND user_account.status = 'E' 包含 SELECT 的 WHERE 子句。