如何在 Ecto 的连接查询中更新两个表中具有相同名称的列

How to update column with the same name in both tables in join query in Ecto

所以 Ecto 中有 update_all 方法,据我所知,我们可以将连接查询传递给它。但后来我意识到我有同名的列,这导致应该更新哪个列的歧义。

Repo.update_all(
  from(d in "dogs",
    inner_join: b in "bones",
    on: b.dog_id == d.id,
    where: d.status != "new",
    where: b.status != "new",
    update: [set: [status: "excellent"]]
  ), []
)

这导致 table dogs 中的 status 列被更新,我如何才能更新 bones table 中的列?

根据其性质,update_all 将更新 from 子句中的 table。如果要更新多个 table,则需要使用 Ecto.Multi

可能有一种方法可以完全使用 SQL 来做到这一点,但我们对 Ecto 的期望是让事情变得更简单,对吧?

所以,首先,使用字符串作为 table 是可以接受的table,但你真的需要知道你在做什么。您基本上绕过了 Ecto 为您设置的与数据库交互的所有内容。 通常,您需要的是 Dog 的模式和 Bone 的模式。 Please refer to the excellent Ecto documentation.

然后我们有 Ecto.Multi,它基本上收集了一堆数据库交互,然后在一个事务中执行所有内容。 Please look at the Ecto.Multi docs as well and pay special attention to Ecto.Multi.update_all/5

例如:

dog_query = from(
  dogs in Dog,
  dogs.status != "new"
)

bone_query =  from(
  bones in Bone,
  bones.status != "new"
)

Ecto.Multi.new()
|> Ecto.Multi.update_all(:dogs, dog_query, set: [status: "new"])
|> Ecto.Multi.update_all(:bones, bone_query, set: [status: "new"])
|> Repo.transaction()

# I think this returns {:ok, %{dogs: [_all_updated_dogs], bones: [_all_updated_bones]}}

这将在一个事务中执行两个更新,这意味着在更新 dogs 和 bones 时不能更改行(使用数据库锁和事务。)

您可以 运行 与任何类型的 queryable 组合,所以如果您坚持直接使用 table 名称,您可以继续将 Dog 替换为"dogs",但我建议使用模式来阐明您的模式。

编辑:还有我的宠物,请在你的 ecto 查询中使用全名 - d b 看起来很相似......想象一下 b 的大查询d db, qd,等等,那代表什么?我知道!请命名您的变量。