Scala slick - 如何从不同的表中获取列值

时间:2016-11-15 21:51:18

标签: scala slick slick-3.0

我有2个表:Main和Update,列名,id和部门。 我想首先阅读Main表,如果department字段值为空,我想从Update表中读取它。

例如,从下表中,我应该从Update表中获取KING的部门值。

如何使用scala slick实现这一点而不运行普通的sql查询?

主要

+-------+----+------------+
+ name  | id | department +            
+-------+----+------------+
| KING  | 10 |            |
| BLAKE | 30 | SALES      |
+-------+----+------------+

更新

+-------+----+------------+
+ name  | id | department +  
+-------+----+------------+
| KING  | 10 | SYSTEMS    |
| BLAKE | 30 | SALES      |
+-------+----+------------+

这是普通的SQL查询

SELECT 
m.`name`,
m.`id`,
if(m.`department`='', u.`department`) as `department`
FROM `Main` m
FROM `Update` u ON m.id=u.id

到目前为止,我已经定义了以下代码......

case class Main(name: Option[String],
                id: Option[int],
                department: Option[String])

case class Update(name: Option[String],
                  id: Option[int],
                  department: Option[String])

lazy val mainQuery = TableQuery[MainTableDefinition]
lazy val updateQuery = TableQuery[UpdateTableDefinition]

class MainTableDefinition(tag: Tag) extends Table[Main](tag, "Main") {
      def name = column[Option[String]]("name")
      def id = column[Option[int]]("id")
      def department = column[Option[String]]("department")

      override def * =
         (name, id, department)<> (Main.tupled, Main.unapply)
}

class UpdateTableDefinition(tag: Tag) extends Table[Update](tag, "Update") {
      def name = column[Option[String]]("name")
      def id = column[Option[int]]("id")
      def department = column[Option[String]]("department")

      override def * =
         (name, id, department)<> (Update.tupled, Update.unapply)
}

val query = for {
  m <- mainQuery 
  u <- updateQuery if m.id === u.id
} yield (m, u)

db.run(query.to[List].result)

1 个答案:

答案 0 :(得分:1)

首先是你的例子:

SELECT 
m.`name`,
m.`id`,
if(m.`department`='', u.`department`) as `department`
FROM `Main` m
FROM `Update` u ON m.id=u.id

似乎从两个表中获取值的组合。

数据库级解决方案

在数据库级别上,这样的事情对你有用:

val query = for {
  m <- mainQuery 
  u <- updateQuery if m.id === u.id
} yield {
  (m.id, m.name, m.department.ifNull(u.department))
}

我认为这是非常接近您原始的,期望的查询(虽然说实话我并不完全确定ifNull如何在所有数据库上翻译。)

应用程序级解决方案

在应用程序级别,假设您有单个案例类:

case class NameDepartment(name: Option[String],
                  id: Option[int],
                  department: Option[String])

(你可以为两个表定义的解包类型,因为它们是相同的)它可能看起来像这样:

  val fetchOperation = (for {
    m <- mainQuery 
    u <- updateQuery if m.id === u.id
  } yield (m, u)
  ).result.map { results => 
    results.map { case (m, u) =>
       NameDepartment(m.name, m.id, m.department.orElse(u.department))
     }
  }