【问题标题】:Conditonally UPDATE fields with Slick String interpolation使用 Slick String 插值有条件地更新字段
【发布时间】:2013-08-09 17:08:33
【问题描述】:

我有两个Options:

val name: Option[String] = ...
val shared: Option[Boolean] = ...

如果上面的值为Some,我想构建一个UPDATE 查询SETs 这些字段,但如果它们是None,则保持不变。

我已经设法做到了这一点,但我不太热衷于检查逗号,如果我需要添加额外的列,它不会扩展。我也不太热衷于使用var

 var query = Q.u + "UPDATE wishlist SET"
 if(name.isDefined)  query = query + " name = " +? name + (if (share.isDefined) ", " else "")
 if(shared.isDefined) query = query + " shared = " +? share

如果我不关心 SQL 注入,我可以执行以下操作:

 val fields = List(
   name.map(n => s"name = '$n'"),
   shared.map(e => s"shared = $e")
 ).flatten

 s"UPDATE wishlist SET ${fields.mkString(", ")}"

问题:有没有更好的方法来使用 Slick 的普通 SQL/String 插值来做到这一点,还是我唯一的选择是转向提升嵌入式?

【问题讨论】:

    标签: scala slick


    【解决方案1】:

    它不是超级优雅,但我认为它至少是灵活的,因为它将扩展到支持许多输入而不改变底层逻辑:

     val name:Option[String] = Some("foo")
     val share:Option[String] = Some("bar")
    
     val sets = List(
       name.map(n => (" name = ", n)),
       share.map(s => (" shared = ", s))
     ).flatten
    
     val query2 = sets.zipWithIndex.foldLeft(Q.u + "UPDATE wishlist SET"){
       case (q,(p,0)) => q + p._1 +? p._2
       case (q,(p,i)) => q + "," + p._1 +? p._2
     }
    

    我将字段名称和值对作为Tuples 的选项放入列表中,然后展平以删除Nones。然后,我将折叠以生成最终语句,并考虑到超过第一部分的任何查询部分都需要一个逗号。

    【讨论】:

    • 谢谢!那肯定更好。
    • 原来这在使用混合类型时不起作用。这是因为+? 方法使用了类型类。它使用参数的类型来查找关联的SetParameter 实例:def +? [T](v: T)(implicit p: SetParameter[T])。在这段代码中,如果nameStringshareBoolean,那么sets 就变成了List[(String,Any)] 并且您可以想象,使用Any 调用+? 将不起作用.作为一种解决方法,我最终编写了几行样板文件来在创建 sets 之前解析类型类。我的代码现在看起来像 this
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-21
    • 2012-01-15
    • 1970-01-01
    • 1970-01-01
    • 2015-01-10
    相关资源
    最近更新 更多