【问题标题】:Using DB Function (TRIM(LEADING '0' from column)) in Slick在 Slick 中使用 DB 函数 (TRIM(LEADING '0' from column))
【发布时间】:2016-02-02 14:17:13
【问题描述】:

我想将一个 SQL 查询翻译成一个TableQuery

SELECT ..., TRIM(LEADING '0' FROM mycolumn) FROM mytable WHERE TRIM(LEADING '0' FROM mycolumn) = '$key

应该变成MyTableQuery.filter(<_.mycolumn something something> )

我不能使用implicit MappedColumnType,因为我正在从String 映射到String,并且结果中有其他String 列。而且我不知道如何在SELECTWHERE 中使用它

对于SELECT 部分,我创建了一个自定义函数,用于将结果元组映射到我的案例类,因此我只需要WHERE 部分的解决方案。

已阅读文档中的Coming from SQLUser defined features,但不幸的是,我并不聪明。我想我可以使用SimpleFunction.unary[String, String],但还没有弄清楚如何使用。

我会用dropLeft 修剪常规的String,但是Rep[String] 没有这样的方法。 ltrim 不接受参数。 endsWith 在我的情况下是模棱两可的。

我无法填充我的查询String,因为并非数据库中的所有值都被填充并且具有不同的长度。

我绝对可以使用纯 SQL 并映射结果,但我真的很想了解我在这里缺少什么。

我正在使用 Slick 3.1.1

【问题讨论】:

    标签: sql scala slick slick-3.0


    【解决方案1】:

    TRIM(LEADING) 稍微奇怪的语法意味着您必须放弃使用 SimpleExpression 并使用可让您访问的 QueryBuilder。

    val trimLeading = SimpleExpression.binary[String, String, String] {
      (trimChar, str, queryBuilder) =>
        import slick.util.MacroSupport._
        import queryBuilder._
        b"TRIM(LEADING $trimChar FROM $str)"
    }
    

    这是一个练习它的例子

    import com.typesafe.config.ConfigFactory
    import slick.backend.DatabaseConfig
    import slick.driver.JdbcProfile
    import scala.concurrent.duration.Duration
    import scala.concurrent.Await
    
    object TrimLeading extends App {
      def trimLeadingExample(dbConfig: DatabaseConfig[JdbcProfile]): Unit = {
        import dbConfig.driver.api._
        val trimLeading = SimpleExpression.binary[String, String, String] {
          (trimChar, str, queryBuilder) =>
            import slick.util.MacroSupport._
            import queryBuilder._
            b"TRIM(LEADING $trimChar FROM $str)"
        }
    
        class ZeroTable(tag: Tag) extends Table[String](tag, "ZeroTable") {
          def zeros = column[String]("zeros")
          def * = zeros
        }
        val zeroTable = TableQuery[ZeroTable]
        exec(zeroTable.schema.create)
        exec(zeroTable ++= Seq("000000x", "00x", "000000000x", "00000x", "00xx"))
    
        exec(zeroTable.
              filter(s => trimLeading("0", s.zeros) === "x").
              map(s => trimLeading("0", s.zeros)).result).foreach(println)
        exec(zeroTable.schema.drop)
        def exec[T](action: DBIO[T]): T = Await.result(dbConfig.db.run(action), Duration.Inf)
      }
      val configStr =
        """
          |  driver = "freeslick.OracleProfile$"
          |  db {
          |    driver = oracle.jdbc.OracleDriver
          |    url="jdbc:oracle:thin:@//localhost:49161/xe"
          |    properties = {
          |      databaseName = "freeslicktest"
          |      user = "system"
          |      password = "oracle"
          |    }
          |  }
        """.stripMargin
      trimLeadingExample(DatabaseConfig.forConfig[JdbcProfile]("", ConfigFactory.parseString(configStr)))
    }
    

    从日志来看,声明是

    *** (s.jdbc.JdbcBackend.statement) Preparing statement: select TRIM(LEADING '0' FROM "zeros") from "ZeroTable" where TRIM(LEADING '0' FROM "zeros") = 'x'

    【讨论】:

    • 哇,谢谢 Sue C,效果很好!至少在 where 子句中,我真的需要它。在 select 子句 (map) 中使用 SimpleExpression 只有在我可以返回元组时才能正常工作。也许你可以看看the follow-up question?不是什么大问题,只是好奇。
    猜你喜欢
    • 2017-04-08
    • 2012-04-29
    • 2017-07-04
    • 1970-01-01
    • 1970-01-01
    • 2023-01-15
    • 1970-01-01
    • 1970-01-01
    • 2012-05-13
    相关资源
    最近更新 更多