SqlAlchemy 2.0 中文文档(十五)(4)

简介: SqlAlchemy 2.0 中文文档(十五)

SqlAlchemy 2.0 中文文档(十五)(3)https://developer.aliyun.com/article/1562981


同时选择多个 ORM 实体

select() 函数一次接受任意数量的 ORM 类和/或列表达式,包括可以请求多个 ORM 类的情况。当从多个 ORM 类中进行 SELECT 时,它们在每个结果行中基于其类名命名。在下面的示例中,对 UserAddress 进行 SELECT 的结果行将以 UserAddress 为名称进行引用:

>>> stmt = select(User, Address).join(User.addresses).order_by(User.id, Address.id)
>>> for row in session.execute(stmt):
...     print(f"{row.User.name} {row.Address.email_address}")
SELECT  user_account.id,  user_account.name,  user_account.fullname,
address.id  AS  id_1,  address.user_id,  address.email_address
FROM  user_account  JOIN  address  ON  user_account.id  =  address.user_id
ORDER  BY  user_account.id,  address.id
[...]  ()
spongebob spongebob@sqlalchemy.org
sandy sandy@sqlalchemy.org
sandy squirrel@squirrelpower.org
patrick pat999@aol.com
squidward stentcl@sqlalchemy.org

如果我们想要为这些实体在行中分配不同的名称,我们将使用 aliased() 构造,并使用 aliased.name 参数将它们别名为具有显式名称的实体:

>>> from sqlalchemy.orm import aliased
>>> user_cls = aliased(User, name="user_cls")
>>> email_cls = aliased(Address, name="email")
>>> stmt = (
...     select(user_cls, email_cls)
...     .join(user_cls.addresses.of_type(email_cls))
...     .order_by(user_cls.id, email_cls.id)
... )
>>> row = session.execute(stmt).first()
SELECT  user_cls.id,  user_cls.name,  user_cls.fullname,
email.id  AS  id_1,  email.user_id,  email.email_address
FROM  user_account  AS  user_cls  JOIN  address  AS  email
ON  user_cls.id  =  email.user_id  ORDER  BY  user_cls.id,  email.id
[...]  ()
>>> print(f"{row.user_cls.name}  {row.email.email_address}")
spongebob spongebob@sqlalchemy.org

上面的别名形式在使用关系来在别名目标之间进行连接中进一步讨论。

现有的 Select 结构也可以使用 Select.add_columns() 方法将 ORM 类和/或列表达式添加到其列子句中。我们也可以使用这种形式来生成与上面相同的语句:

>>> stmt = (
...     select(User).join(User.addresses).add_columns(Address).order_by(User.id, Address.id)
... )
>>> print(stmt)
SELECT  user_account.id,  user_account.name,  user_account.fullname,
address.id  AS  id_1,  address.user_id,  address.email_address
FROM  user_account  JOIN  address  ON  user_account.id  =  address.user_id
ORDER  BY  user_account.id,  address.id 

选择单个属性

映射类上的属性,如 User.nameAddress.email_address,当传递给 select() 时,可以像 Column 或其他 SQL 表达式对象一样使用。创建针对特定列的 select() 将返回 Row 对象,而不是像 UserAddress 对象那样的实体。每个 Row 将分别表示每个列:

>>> result = session.execute(
...     select(User.name, Address.email_address)
...     .join(User.addresses)
...     .order_by(User.id, Address.id)
... )
SELECT  user_account.name,  address.email_address
FROM  user_account  JOIN  address  ON  user_account.id  =  address.user_id
ORDER  BY  user_account.id,  address.id
[...]  () 

上面的语句返回具有 nameemail_address 列的 Row 对象,如下运行时演示所示:

>>> for row in result:
...     print(f"{row.name}  {row.email_address}")
spongebob  spongebob@sqlalchemy.org
sandy  sandy@sqlalchemy.org
sandy  squirrel@squirrelpower.org
patrick  pat999@aol.com
squidward  stentcl@sqlalchemy.org

使用 Bundle 分组选择的属性

Bundle 构造是一个可扩展的仅限 ORM 的构造,允许将列表达式集合分组在结果行中:

>>> from sqlalchemy.orm import Bundle
>>> stmt = select(
...     Bundle("user", User.name, User.fullname),
...     Bundle("email", Address.email_address),
... ).join_from(User, Address)
>>> for row in session.execute(stmt):
...     print(f"{row.user.name} {row.user.fullname} {row.email.email_address}")
SELECT  user_account.name,  user_account.fullname,  address.email_address
FROM  user_account  JOIN  address  ON  user_account.id  =  address.user_id
[...]  ()
spongebob Spongebob Squarepants spongebob@sqlalchemy.org
sandy Sandy Cheeks sandy@sqlalchemy.org
sandy Sandy Cheeks squirrel@squirrelpower.org
patrick Patrick Star pat999@aol.com
squidward Squidward Tentacles stentcl@sqlalchemy.org

Bundle 可能对创建轻量级视图和自定义列分组很有用。Bundle 也可以被子类化以返回替代数据结构;请参见 Bundle.create_row_processor() 以获取示例。

另请参阅

Bundle

Bundle.create_row_processor()

选择 ORM 别名

如使用别名教程中所述,创建 ORM 实体的 SQL 别名是通过对映射类使用 aliased() 构造完成的:

>>> from sqlalchemy.orm import aliased
>>> u1 = aliased(User)
>>> print(select(u1).order_by(u1.id))
SELECT  user_account_1.id,  user_account_1.name,  user_account_1.fullname
FROM  user_account  AS  user_account_1  ORDER  BY  user_account_1.id 

就像使用Table.alias()时一样,SQL 别名是匿名命名的。对于从具有显式名称的行中选择实体的情况,也可以传递aliased.name参数:

>>> from sqlalchemy.orm import aliased
>>> u1 = aliased(User, name="u1")
>>> stmt = select(u1).order_by(u1.id)
>>> row = session.execute(stmt).first()
SELECT  u1.id,  u1.name,  u1.fullname
FROM  user_account  AS  u1  ORDER  BY  u1.id
[...]  ()
>>> print(f"{row.u1.name}")
spongebob

另请参阅

aliased结构对于多种用例至关重要,包括:

  • 利用 ORM 的子查询;章节从子查询中选择实体和与子查询连接进一步讨论了这一点。
  • 控制结果集中实体的名称;参见同时选择多个 ORM 实体以获取示例
  • 多次连接到同一 ORM 实体;参见使用关系在别名目标之间连接以获取示例。

从文本语句中获取 ORM 结果

对象关系映射(ORM)支持从其他来源的 SELECT 语句加载实体。典型用例是文本 SELECT 语句,在 SQLAlchemy 中使用text()结构表示。text()结构可以附加有关语句将加载的 ORM 映射列的信息;然后可以将其与 ORM 实体本身关联,以便基于此语句加载 ORM 对象。

给定要加载的文本 SQL 语句:

>>> from sqlalchemy import text
>>> textual_sql = text("SELECT id, name, fullname FROM user_account ORDER BY id")

我们可以使用TextClause.columns()方法向语句添加列信息;当调用此方法时,TextClause对象将转换为TextualSelect对象,其承担的角色可与Select构造类似。TextClause.columns()方法通常传递Column对象或等效对象,在这种情况下,我们可以直接使用User类上的 ORM 映射属性:

>>> textual_sql = textual_sql.columns(User.id, User.name, User.fullname)

现在,我们有一个经过 ORM 配置的 SQL 构造,可以分别加载“id”、“name”和“fullname”列。要将此 SELECT 语句用作完整User实体的来源,我们可以使用Select.from_statement()方法将这些列链接到常规的 ORM 启用的Select构造中:

>>> orm_sql = select(User).from_statement(textual_sql)
>>> for user_obj in session.execute(orm_sql).scalars():
...     print(user_obj)
SELECT  id,  name,  fullname  FROM  user_account  ORDER  BY  id
[...]  ()
User(id=1, name='spongebob', fullname='Spongebob Squarepants')
User(id=2, name='sandy', fullname='Sandy Cheeks')
User(id=3, name='patrick', fullname='Patrick Star')
User(id=4, name='squidward', fullname='Squidward Tentacles')
User(id=5, name='ehkrabs', fullname='Eugene H. Krabs')

相同的TextualSelect对象也可以使用TextualSelect.subquery()方法转换为子查询,并使用aliased()构造将其链接到User实体,方式与下面讨论的从子查询中选择实体类似:

>>> orm_subquery = aliased(User, textual_sql.subquery())
>>> stmt = select(orm_subquery)
>>> for user_obj in session.execute(stmt).scalars():
...     print(user_obj)
SELECT  anon_1.id,  anon_1.name,  anon_1.fullname
FROM  (SELECT  id,  name,  fullname  FROM  user_account  ORDER  BY  id)  AS  anon_1
[...]  ()
User(id=1, name='spongebob', fullname='Spongebob Squarepants')
User(id=2, name='sandy', fullname='Sandy Cheeks')
User(id=3, name='patrick', fullname='Patrick Star')
User(id=4, name='squidward', fullname='Squidward Tentacles')
User(id=5, name='ehkrabs', fullname='Eugene H. Krabs')

直接使用TextualSelectSelect.from_statement()相比,使用aliased()的区别在于,在前一种情况下,生成的 SQL 中不会产生子查询。在某些情况下,这可能有利于性能或复杂性方面。

从子查询中选择实体

在前一节讨论的aliased()构造中,可以与任何Subuqery构造一起使用,该构造来自诸如Select.subquery()之类的方法,以将 ORM 实体链接到该子查询返回的列;子查询返回的列与实体映射的列之间必须存在列对应关系,这意味着子查询最终需要源自这些实体,例如下面的示例:

>>> inner_stmt = select(User).where(User.id < 7).order_by(User.id)
>>> subq = inner_stmt.subquery()
>>> aliased_user = aliased(User, subq)
>>> stmt = select(aliased_user)
>>> for user_obj in session.execute(stmt).scalars():
...     print(user_obj)
  SELECT  anon_1.id,  anon_1.name,  anon_1.fullname
FROM  (SELECT  user_account.id  AS  id,  user_account.name  AS  name,  user_account.fullname  AS  fullname
FROM  user_account
WHERE  user_account.id  <  ?  ORDER  BY  user_account.id)  AS  anon_1
[generated  in  ...]  (7,)
User(id=1, name='spongebob', fullname='Spongebob Squarepants')
User(id=2, name='sandy', fullname='Sandy Cheeks')
User(id=3, name='patrick', fullname='Patrick Star')
User(id=4, name='squidward', fullname='Squidward Tentacles')
User(id=5, name='ehkrabs', fullname='Eugene H. Krabs')

另请参见

ORM 实体子查询/CTEs - 在 SQLAlchemy 统一教程中

加入子查询

从 UNION 和其他集合操作中选择实体

union()union_all() 函数是最常见的集合操作,与其他集合操作(如 except_()intersect() 等)一起,提供了一个称为 CompoundSelect 的对象,它由多个通过集合操作关键字连接的 Select 构造组成。ORM 实体可以通过简单的复合选择使用 Select.from_statement() 方法进行选择,该方法在 从文本语句中获取 ORM 结果 中已经说明。在这种方法中,UNION 语句是将被渲染的完整语句,不能在使用 Select.from_statement() 后添加额外的条件:

>>> from sqlalchemy import union_all
>>> u = union_all(
...     select(User).where(User.id < 2), select(User).where(User.id == 3)
... ).order_by(User.id)
>>> stmt = select(User).from_statement(u)
>>> for user_obj in session.execute(stmt).scalars():
...     print(user_obj)
SELECT  user_account.id,  user_account.name,  user_account.fullname
FROM  user_account
WHERE  user_account.id  <  ?  UNION  ALL  SELECT  user_account.id,  user_account.name,  user_account.fullname
FROM  user_account
WHERE  user_account.id  =  ?  ORDER  BY  id
[generated  in  ...]  (2,  3)
User(id=1, name='spongebob', fullname='Spongebob Squarepants')
User(id=3, name='patrick', fullname='Patrick Star')

CompoundSelect 构造可以在更灵活的查询中更灵活地使用,该查询可以通过将其组织成子查询并使用 aliased() 将其链接到 ORM 实体来进一步修改,如 从子查询中选择实体 中已说明。在下面的示例中,我们首先使用 CompoundSelect.subquery() 创建 UNION ALL 语句的子查询,然后将其打包到 aliased() 构造中,在这里它可以像其他映射实体一样用于 select() 构造中,包括我们可以根据其导出的列添加过滤和排序条件:

>>> subq = union_all(
...     select(User).where(User.id < 2), select(User).where(User.id == 3)
... ).subquery()
>>> user_alias = aliased(User, subq)
>>> stmt = select(user_alias).order_by(user_alias.id)
>>> for user_obj in session.execute(stmt).scalars():
...     print(user_obj)
SELECT  anon_1.id,  anon_1.name,  anon_1.fullname
FROM  (SELECT  user_account.id  AS  id,  user_account.name  AS  name,  user_account.fullname  AS  fullname
FROM  user_account
WHERE  user_account.id  <  ?  UNION  ALL  SELECT  user_account.id  AS  id,  user_account.name  AS  name,  user_account.fullname  AS  fullname
FROM  user_account
WHERE  user_account.id  =  ?)  AS  anon_1  ORDER  BY  anon_1.id
[generated  in  ...]  (2,  3)
User(id=1, name='spongebob', fullname='Spongebob Squarepants')
User(id=3, name='patrick', fullname='Patrick Star')

另请参阅

从 Union 中选择 ORM 实体 - 在 SQLAlchemy 统一教程 中

连接

Select.join()Select.join_from()方法用于构建针对 SELECT 语句的 SQL JOINs。

本节将详细介绍这些方法在 ORM 中的用例。有关从 Core 视角的使用的一般概述,请参阅显式 FROM 子句和 JOINs 中的 SQLAlchemy 统一教程。

在 ORM 上下文中使用Select.join()进行 2.0 风格查询的用法基本上等同于除了遗留用例之外,在 1.x 风格查询中使用Query.join()方法的用法。

简单的关系连接

考虑两个类UserAddress之间的映射,其中关系User.addresses表示与每个User关联的Address对象的集合。Select.join()最常见的用法是沿着这种关系创建一个 JOIN,使用User.addresses属性作为指示器来指示应该如何发生这种情况:

>>> stmt = select(User).join(User.addresses)

在上面的例子中,对Select.join()User.addresses的调用将导致大致等效的 SQL 语句:

>>> print(stmt)
SELECT  user_account.id,  user_account.name,  user_account.fullname
FROM  user_account  JOIN  address  ON  user_account.id  =  address.user_id 

在上面的例子中,我们将User.addresses称为传递给Select.join()的“on clause”,即它指示如何构建 JOIN 的“ON”部分。

提示

请注意,使用Select.join()从一个实体连接到另一个实体会影响 SELECT 语句的 FROM 子句,但不会影响列子句;在这个示例中,SELECT 语句将继续仅返回User实体的行。要同时从UserAddress中选择列/实体,必须在select()函数中也命名Address实体,或者在使用Select.add_columns()方法后将其添加到Select构造中。有关这两种形式的示例,请参阅同时选择多个 ORM 实体部分。

链式多重连接

要构建连接链,可以使用多个Select.join()调用。关联属性同时涵盖连接的左侧和右侧。考虑额外的实体OrderItem,其中User.orders关系指向Order实体,而Order.items关系指向Item实体,通过一个关联表order_items。两个Select.join()调用将导致第一个 JOIN 从UserOrder,第二个从OrderItem。然而,由于Order.items是多对多关系,它会导致两个独立的 JOIN 元素,总共有三个 JOIN 元素在结果 SQL 中:

>>> stmt = select(User).join(User.orders).join(Order.items)
>>> print(stmt)
SELECT  user_account.id,  user_account.name,  user_account.fullname
FROM  user_account
JOIN  user_order  ON  user_account.id  =  user_order.user_id
JOIN  order_items  AS  order_items_1  ON  user_order.id  =  order_items_1.order_id
JOIN  item  ON  item.id  =  order_items_1.item_id 

每次调用Select.join()方法的顺序只有在我们想要从中连接的“左”侧需要出现在 FROM 列表中时才重要,然后我们才能指示一个新的目标。例如,如果我们指定select(User).join(Order.items).join(User.orders)Select.join()就不会知道如何正确地进行连接,它会引发错误。在正确的实践中,应该以与我们希望在 SQL 中呈现 JOIN 子句相匹配的方式调用Select.join()方法,并且每次调用都应该表示从前面的内容清晰链接。

我们在 FROM 子句中定位的所有元素仍然可用作继续连接 FROM 的潜在点。例如,我们可以继续将其他元素添加到上述User实体的 FROM 连接中,例如在我们的连接链中添加User.addresses关系:

>>> stmt = select(User).join(User.orders).join(Order.items).join(User.addresses)
>>> print(stmt)
SELECT  user_account.id,  user_account.name,  user_account.fullname
FROM  user_account
JOIN  user_order  ON  user_account.id  =  user_order.user_id
JOIN  order_items  AS  order_items_1  ON  user_order.id  =  order_items_1.order_id
JOIN  item  ON  item.id  =  order_items_1.item_id
JOIN  address  ON  user_account.id  =  address.user_id 

连接到目标实体

第二种形式的Select.join()允许将任何映射实体或核心可选择的构造作为目标。在此用法中,Select.join() 将尝试推断JOIN 的 ON 子句,使用两个实体之间的自然外键关系:

>>> stmt = select(User).join(Address)
>>> print(stmt)
SELECT  user_account.id,  user_account.name,  user_account.fullname
FROM  user_account  JOIN  address  ON  user_account.id  =  address.user_id 

在上述调用形式中,Select.join() 被调用以自动推断“on clause”。如果两个映射的Table构造之间没有设置任何ForeignKeyConstraint,或者如果它们之间有多个ForeignKeyConstraint链接,使得要使用的适当约束不明确,此调用形式最终将引发错误。

注意

在使用Select.join()Select.join_from()而不指定 ON 子句时,ORM 配置的relationship()构造不会被考虑。仅在尝试为 JOIN 推断 ON 子句时,才会在映射的Table对象级别上查阅配置的ForeignKeyConstraint关系。

到具有 ON 子句的目标的连接

第三种调用形式允许显式传递目标实体以及 ON 子句。包含 SQL 表达式作为 ON 子句的示例如下:

>>> stmt = select(User).join(Address, User.id == Address.user_id)
>>> print(stmt)
SELECT  user_account.id,  user_account.name,  user_account.fullname
FROM  user_account  JOIN  address  ON  user_account.id  =  address.user_id 

基于表达式的 ON 子句也可以是一个relationship()绑定属性,就像在简单关系连接中使用的方式一样:

>>> stmt = select(User).join(Address, User.addresses)
>>> print(stmt)
SELECT  user_account.id,  user_account.name,  user_account.fullname
FROM  user_account  JOIN  address  ON  user_account.id  =  address.user_id 

上述示例似乎多余,因为它以两种不同的方式指示了Address的目标;然而,当加入到别名实体时,这种形式的实用性变得明显;请参见使用关系连接别名目标中的示例。### 将关系与自定义 ON 条件结合使用

relationship()构造生成的 ON 子句可以通过附加的额外条件进行增强。这对于快速限制特定关系路径上连接范围的方式以及配置加载策略(如joinedload()selectinload())非常有用。PropComparator.and_()方法按位置接受一系列 SQL 表达式,这些表达式将通过 AND 连接到 JOIN 的 ON 子句。例如,如果我们想要从User JOIN 到Address,但也限制 ON 条件仅适用于某些电子邮件地址:

>>> stmt = select(User.fullname).join(
...     User.addresses.and_(Address.email_address == "squirrel@squirrelpower.org")
... )
>>> session.execute(stmt).all()
SELECT  user_account.fullname
FROM  user_account
JOIN  address  ON  user_account.id  =  address.user_id  AND  address.email_address  =  ?
[...]  ('squirrel@squirrelpower.org',)
[('Sandy Cheeks',)]

另请参阅

PropComparator.and_()方法也适用于加载策略,如joinedload()selectinload()。请参见向加载选项添加条件部分。### 使用关系连接别名目标

当使用relationship()绑定属性构建连接以指示 ON 子句时,使用带有 ON 子句的目标的连接中说明的两参数语法可以扩展为与aliased()构造一起使用,以指示 SQL 别名作为连接的目标,同时仍然利用relationship()绑定属性来指示 ON 子句,如下例所示,其中User实体两次与两个不同的aliased()构造连接到Address实体:

>>> address_alias_1 = aliased(Address)
>>> address_alias_2 = aliased(Address)
>>> stmt = (
...     select(User)
...     .join(address_alias_1, User.addresses)
...     .where(address_alias_1.email_address == "patrick@aol.com")
...     .join(address_alias_2, User.addresses)
...     .where(address_alias_2.email_address == "patrick@gmail.com")
... )
>>> print(stmt)
SELECT  user_account.id,  user_account.name,  user_account.fullname
FROM  user_account
JOIN  address  AS  address_1  ON  user_account.id  =  address_1.user_id
JOIN  address  AS  address_2  ON  user_account.id  =  address_2.user_id
WHERE  address_1.email_address  =  :email_address_1
AND  address_2.email_address  =  :email_address_2 

同样的模式可以更简洁地使用修饰符 PropComparator.of_type() 表达,该修饰符可以应用于 relationship() 绑定的属性,传递目标实体以一步指示目标。下面的示例使用 PropComparator.of_type() 来生成与刚刚示例相同的 SQL 语句:

>>> print(
...     select(User)
...     .join(User.addresses.of_type(address_alias_1))
...     .where(address_alias_1.email_address == "patrick@aol.com")
...     .join(User.addresses.of_type(address_alias_2))
...     .where(address_alias_2.email_address == "patrick@gmail.com")
... )
SELECT  user_account.id,  user_account.name,  user_account.fullname
FROM  user_account
JOIN  address  AS  address_1  ON  user_account.id  =  address_1.user_id
JOIN  address  AS  address_2  ON  user_account.id  =  address_2.user_id
WHERE  address_1.email_address  =  :email_address_1
AND  address_2.email_address  =  :email_address_2 

要利用一个 relationship() 来构建一个从别名实体连接的连接,该属性直接从 aliased() 构造中可用:

>>> user_alias_1 = aliased(User)
>>> print(select(user_alias_1.name).join(user_alias_1.addresses))
SELECT  user_account_1.name
FROM  user_account  AS  user_account_1
JOIN  address  ON  user_account_1.id  =  address.user_id 
```### 连接到子查询
连接的目标可以是任何可选择的实体,包括子查询。在使用 ORM 时,通常会以 `aliased()` 构造来表示这些目标,但这并不是严格要求的,特别是如果连接的实体不会在结果中返回时。例如,要从 `User` 实体连接到 `Address` 实体,在这里 `Address` 实体被表示为一行限制的子查询,我们首先使用 `Select.subquery()` 构造一个 `Subquery` 对象,然后可以将其用作 `Select.join()` 方法的目标:
```py
>>> subq = select(Address).where(Address.email_address == "pat999@aol.com").subquery()
>>> stmt = select(User).join(subq, User.id == subq.c.user_id)
>>> print(stmt)
SELECT  user_account.id,  user_account.name,  user_account.fullname
FROM  user_account
JOIN  (SELECT  address.id  AS  id,
address.user_id  AS  user_id,  address.email_address  AS  email_address
FROM  address
WHERE  address.email_address  =  :email_address_1)  AS  anon_1
ON  user_account.id  =  anon_1.user_id 

上述的 SELECT 语句在通过 Session.execute() 调用时将返回包含 User 实体的行,但不包含 Address 实体。为了将 Address 实体包含到将在结果集中返回的实体集合中,我们构造了一个针对 Address 实体和 Subquery 对象的 aliased() 对象。我们还可以希望对 aliased() 构造应用一个名称,例如下面使用的 "address",这样我们就可以在结果行中通过名称引用它:

>>> address_subq = aliased(Address, subq, name="address")
>>> stmt = select(User, address_subq).join(address_subq)
>>> for row in session.execute(stmt):
...     print(f"{row.User} {row.address}")
SELECT  user_account.id,  user_account.name,  user_account.fullname,
anon_1.id  AS  id_1,  anon_1.user_id,  anon_1.email_address
FROM  user_account
JOIN  (SELECT  address.id  AS  id,
address.user_id  AS  user_id,  address.email_address  AS  email_address
FROM  address
WHERE  address.email_address  =  ?)  AS  anon_1  ON  user_account.id  =  anon_1.user_id
[...]  ('pat999@aol.com',)
User(id=3, name='patrick', fullname='Patrick Star') Address(id=4, email_address='pat999@aol.com')


SqlAlchemy 2.0 中文文档(十五)(5)https://developer.aliyun.com/article/1562983

相关文章
|
4月前
|
SQL 存储 数据库
SqlAlchemy 2.0 中文文档(十一)(4)
SqlAlchemy 2.0 中文文档(十一)
51 11
|
4月前
|
SQL 关系型数据库 MySQL
SqlAlchemy 2.0 中文文档(十七)(2)
SqlAlchemy 2.0 中文文档(十七)
37 4
|
4月前
|
SQL 关系型数据库 API
SqlAlchemy 2.0 中文文档(十七)(4)
SqlAlchemy 2.0 中文文档(十七)
78 4
|
4月前
|
SQL 关系型数据库 数据库
SqlAlchemy 2.0 中文文档(十七)(3)
SqlAlchemy 2.0 中文文档(十七)
40 4
|
4月前
|
SQL 测试技术 数据库
SqlAlchemy 2.0 中文文档(十二)(5)
SqlAlchemy 2.0 中文文档(十二)
26 2
|
4月前
|
SQL Oracle 关系型数据库
SqlAlchemy 2.0 中文文档(十五)(1)
SqlAlchemy 2.0 中文文档(十五)
50 1
|
4月前
|
SQL 测试技术 知识图谱
SqlAlchemy 2.0 中文文档(十五)(3)
SqlAlchemy 2.0 中文文档(十五)
33 1
|
4月前
|
SQL Python
SqlAlchemy 2.0 中文文档(十五)(5)
SqlAlchemy 2.0 中文文档(十五)
78 1
|
4月前
|
SQL 测试技术 API
SqlAlchemy 2.0 中文文档(十五)(2)
SqlAlchemy 2.0 中文文档(十五)
88 1
|
4月前
|
API 数据库 C++
SqlAlchemy 2.0 中文文档(十四)(1)
SqlAlchemy 2.0 中文文档(十四)
31 1