在一个灵活的查询中从多个表中删除行

Posted

技术标签:

【中文标题】在一个灵活的查询中从多个表中删除行【英文标题】:Deleting Rows from multiple tables in a slick query 【发布时间】:2017-02-01 23:25:27 【问题描述】:

我用谷歌搜索并找到了这个帖子Slick 3.0: Delete rows from multiple tables in a transaction 但是解决方案说它不是一个好的解决方案。

我正在使用下面的代码从多个表中删除行

val deleteB = for 
  aId <- TableA.filter(a => a.id === param).map(_.id)
  bId <- TableB.filter(_.aId === aId)
 yield bId

val deleteC = for 
  aId <- TableA.filter(a => a.id === param).map(_.id)
  cId <- TableC.filter(_.aId === aId)
 yield cId

val deleteA = TableA.filter(a.Id === param)

val query = (deleteC.delete andThen deleteB.delete andThen deleteA.delete).transactionally
db.run(query)

但我想知道是否有更好的写法。

我对上述方法的问题是我想返回从 TableA 中删除的行数,而不是从子表 TableB 和 TableC 中删除的行数。

此外,在运行时它会抱怨删除查询中有连接。

【问题讨论】:

我没有看到任何方法问题。它应该可以正常工作..您在删除记录时是否遇到任何具体问题? 更新了问题 【参考方案1】:

我认为你也可以这样做 -

 def buildTransactionQuery = 
    for 
      deleteA <- TableA.filter(a.Id === param)
      deleteB  <- TableB.filter(_.aId === deleteA.map(_.id))
      deleteC  <- TableC.filter(_.aId === deleteA.map(_.id))

      deleteAAction = deleteA.delete
      deleteBAction = deleteB.delete
      deleteCAction = deleteC.delete
      res = (deleteAAction, deleteBAction, deleteCAction)
     yield res
  

  def executeTransactionQuery = 
    val transactionQuery = for 
      queries <- buildTransactionQuery
      action = DBIOAction.seq(queries._3, queries._2, queries._1)
     yield action
    transactionQuery.flatMap(action => db.run(action.transactionally).transform(s => true, t => 
      logger.error(t.getMessage)
      t
    ))
  

【讨论】:

这行得通吗?我认为您正在自己的事务中执行每个操作。但是我们需要在一个事务中运行所有 3 个。 它会工作,在一个事务中执行 3 个操作。【参考方案2】:

以下将解决连接警告/错误。

val deleteB = TableB.filter(_.aid in TableA.filter(a => a.id === id).map(_.id))

val deleteC = TableC.filter(_.aid in TableA.filter(a => a.id === id).map(_.id))

val deleteA = TableA.filter(_.id === id)

db.run((deleteB.delete andThen deleteC.delete andThen deleteA.delete).transactionally)

并且由于您使用 andThen 来链接您的操作,因此组合操作将始终返回最后一个操作的受影响行计数,如 here 所述。所以返回的数字始终是从deleteA 操作中删除的行,因为这是andThen 链中的最后一个操作。

然后

在此之后运行另一个操作 动作,如果它成功完成,并返回结果 第二个动作。如果这两个操作中的任何一个失败,则结果 操作也失败了。

【讨论】:

谢谢!这是一个更清洁的解决方案。

以上是关于在一个灵活的查询中从多个表中删除行的主要内容,如果未能解决你的问题,请参考以下文章

从同一查询中的两个表中删除 NULL 行[重复]

在Oracle中从表中删除重复行

如何在 Go 中从 DynamoDB 表中删除多个项目

使用 LINQ 和实体框架在一个 SQL 查询中从多个表中提取数据

如何在spring boot jdbc中从具有批量大小的多个表中执行批量删除

如何在 SAP ASE Sybase 16 中从具有外键的表中删除行