光滑的空值比较

时间:2014-12-19 09:00:47

标签: slick slick-2.0

我遇到了可空列比较的问题。

如果某些列是Option [T],我想知道如何将这些列上的===操作转换为sql。 有两种可能性:null值(scala中为None)和非null值。 在null值的情况下,sql应该使用is而不是=。 但是,在下列情况下,光滑无法正确处理它。

这是代码(使用H2数据库):

object Test1 extends Controller {


  case class User(id: Option[Int], first: String, last: String)

  class Users(tag: Tag) extends Table[User](tag, "users") {
    def id = column[Int]("id",O.Nullable)
    def first = column[String]("first")
    def last = column[String]("last")
    def * = (id.?, first, last) <> (User.tupled, User.unapply)
  }
  val users = TableQuery[Users]


  def find_u(u:User) =  DB.db.withSession{ implicit session =>
    users.filter( x=> x.id === u.id && x.first === u.first && x.last === u.last ).firstOption

  }

  def t1 = Action {
    DB.db.withSession { implicit session =>
      DB.createIfNotExists(users)

      val u1 = User(None,"123","abc")
      val u2 = User(Some(1232),"123","abc")

      users += u1
      val r1 = find_u(u1)
      println(r1)
      val r2 = find_u(u2)
      println(r2)

    }
    Ok("good")
  }
}

我打印出sql。它是第一个find_u的结果。

[debug] s.s.j.J.statement - Preparing statement: select x2."id", x2."first", x2."last" from "users" x2 where (
(x2."id" = null) and (x2."first" = '123')) and (x2."last" = 'abc')

请注意,此处(x2."id" = null)不正确。它应该是(x2."id" is null)

更新

是否可以仅以自动方式比较非空字段?忽略那些空列。 例如。在User(None,"123","abc")的情况下,只执行where (x2."first" = '123')) and (x2."last" = 'abc')

1 个答案:

答案 0 :(得分:1)

Slick使用三值逻辑。这显示了涉及可空列的时间。在这方面,它不遵循Scala语义,而是使用SQL语义。所以(x2."id" = null)在这些设计决策下确实是正确的。要使用x.id.isEmpty进行严格的NULL检查。为了严格比较,

(if(u.id.isEmpty) x.id.isEmpty else (x.id === u.id))

<强>更新

仅在用户标识为非空时才进行比较

(u.id.isEmpty || (x.id === u.id)) && ...