使用光滑创建表视图

时间:2015-09-11 10:16:59

标签: scala slick

如何使用光滑3创建postgresql view查询?

我没有在光滑的文档中找到答案。

与我question相关的问题。我得到了正确答案,但我不知道如何使用光滑实现它。

2 个答案:

答案 0 :(得分:4)

Slick 3中的视图只有基本的支持,不能保证完整的编译时安全性和组合性,后者尤其重要,因为大多数视图都强烈依赖于其他表中的数据。 您可以将视图描述为表和单独的模式操作语句,您必须使用这些语句而不是标准表模式扩展方法,如create和drop。以下是数据库中已存在REGISTRY和ROWS表的your registries-n-rows case的示例:

case class RegRn(id: Int, name: String, count: Long)

trait View{
  val viewName = "REG_RN"
  val registryTableName = "REGISTRY"
  val rowsTableName = "ROWS"

  val profile: JdbcProfile
  import profile.api._

  class RegRns(tag: Tag) extends Table[RegRn](tag, viewName) {

    def id    = column[Int]   ("REGISTRY_ID")
    def name  = column[String]("NAME", O.SqlType("VARCHAR"))
    def count = column[Long]  ("CT", O.SqlType("VARCHAR"))

    override def * = (id, name, count) <> (RegRn.tupled, RegRn.unapply)
    ...
  }

  val regRns = TableQuery[RegRns]
  val createViewSchema = sqlu"""CREATE VIEW #$viewName AS
                                   SELECT R.*, COALESCE(N.ct, 0) AS CT
                                   FROM   #$registryTableName R
                                   LEFT   JOIN (
                                     SELECT REGISTRY_ID, count(*) AS CT
                                     FROM   #$rowsTableName
                                     GROUP  BY REGISTRY_ID
                                   ) N ON R.REGISTRY_ID=N.REGISTRY_ID"""

  val dropViewSchema = sqlu"DROP VIEW #$viewName"
  ...
}

您现在可以使用db.run(createViewSchema)创建一个视图,将其删除db.run(dropViewSchema),当然也可以调用MTable.getTables("REG_RN"),以便找到它的tableType为“VIEW”。查询与其他表格相同,例如 db run regRns.result.head。如果规则允许,您甚至可以像对普通Slick表一样将值插入视图中(不是由于COALESCE和子查询而导致的情况)。 正如我所提到的,当你想要编写现有的表来创建一个视图时,一切都会变得一团糟。您必须始终保持其名称和定义同步,因为现在无法编写任何至少可以保证视图形状符合基础表组合形状的内容。好吧,除了像这样丑陋的人之外别无他法:

trait View{
  val profile: JdbcProfile
  import profile.api._

  val registryTableName = "REGISTRY"
  val registryId   = "REGISTRY_ID"
  val regitsryName = "NAME"

  class Registries(tag: Tag) extends Table[Registry](tag, registryTableName) {

    def id   = column[Int]   (registryId)
    def name = column[String](regitsryName, O.SqlType("VARCHAR"))

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

  val rowsTableName = "ROWS"
  val rowsId  = "ROW_ID"
  val rowsRow = "ROW"

  class Rows(tag: Tag) extends Table[Row](tag, rowsTableName) {

    def id  = column[String](rowsId, O.SqlType("VARCHAR"))
    def rid = column[Int]   (registryId)
    def r   = column[String]("rowsRow", O.SqlType("VARCHAR"))

    override def * = (id, rid, r) <> (Row.tupled, Row.unapply)
    ...
  }

  val viewName = "REG_RN"

  class RegRns(tag: Tag) extends Table[RegRn](tag, viewName) {

    def id    = column[Int]   ("REGISTRY_ID")
    def name  = column[String]("NAME", O.SqlType("VARCHAR"))
    def count = column[Long]  ("CT", O.SqlType("VARCHAR"))

    override def * = (id, name, count) <> (RegRn.tupled, RegRn.unapply)
    ...
  }

  val registries = TableQuery[Registries]
  val rows = TableQuery[Rows]
  val regRns = TableQuery[RegRns]
  val createViewSchema = sqlu"""CREATE VIEW #$viewName AS
                                       SELECT R.*, COALESCE(N.ct, 0) AS CT
                                       FROM   #$registryTableName R
                                       LEFT   JOIN (
                                         SELECT #$registryId, count(*) AS CT
                                         FROM   #$rowsTableName
                                         GROUP  BY #$registryId
                                       ) N ON R.#$registryId=N.#$registryId"""

  val dropViewSchema = sqlu"DROP VIEW #$viewName"
  ...
}

答案 1 :(得分:1)

如何在视图前导后附加查询文本:

val yourAwesomeQryComposition : TableQuery = ...

val qryText = yourAwesomeQryComposition.map(reg => (reg.id, ....)).result.statements.head

val createViewSchema = sqlu"""CREATE VIEW #$viewName AS #${qryText}"""