2

事务块中涉及的表的唯一键约束存在问题。

关键约束的目的是防止一名球员有多个进球或每场比赛-球队-期间-进球时间球员的助攻。这很好用,没有重复的得分记录,太好了。

但是,如果球队选择了错误的得分手或助攻者(例如,球员 A 得到了助攻,但应该得到进球的得分),然后想要更新记录,关键约束会阻止更新作为球员 A 发生,在更新时,将有一个目标和一个助攻在同一目标上。

我应该提到我正在使用 JDBC SQL 包装器,因此我无法直接控制生成的 SQL。

为了解决这个问题,我决定删除现有的目标并插入,所有这些都在一个事务块中。同样的交易,违反了关键约束。是否可以在同一个事务块中删除和插入?生成 SQL 的代码类似于:

db.handle withSession { implicit ss: SS =>
  ss.withTransaction {
    val result = for{
      d <- teams.map{id=> model.delete(gameID, id)}
      s <- rows.map{x=> model.insert(x)}
    } yield s
  }
}
if(result.forall(_.isRight)) Right
else { ss.rollback; Left( i18n("not updated") ) }
4

1 回答 1

0

解决方案是在单个查询中删除整个游戏,或者,如果仅提交 1 个团队的统计数据进行更新(我们的系统允许),则删除该团队的目标游戏的统计数据。

在完整的统计数据删除的情况下,我们有:

db.handle withSession { implicit ss: SS =>
  ss.withTransaction {
    val result = for{
      d <- model.delete(gameID)
      s <- rows.map{x=> model.insert(x)}
    } yield s
  }
}
if(result.forall(_.isRight)) Right
else { ss.rollback; Left( i18n("not updated") ) }

关键在于,似乎无法执行多个删除查询,然后执行多个插入来重新填充事务块中的已删除数据,其中存在键约束,否则会因不删除待插入数据而被破坏。

不确定这是否有意义或者它是否正确;-),但在单个查询中执行删除确实允许随后的插入执行没有问题。

两全其美,可以保持所需的键约束,并执行事务删除/插入(注意:我不能REPLACE INTO,因为 JDBC 包装库不支持它)。

于 2012-12-13T01:21:09.343 回答