Scala Slick:如何将类似SQL的语句与SQL IN语句组合在一起
我基本上希望用更“流畅”的代码替换以下代码: 因此,生成的SQL将是:Scala Slick:如何将类似SQL的语句与SQL IN语句组合在一起,scala,slick,sql-like,sql-in,Scala,Slick,Sql Like,Sql In,我基本上希望用更“流畅”的代码替换以下代码: 因此,生成的SQL将是: SELECT u.first_name, u.last_name FROM users u WHERE last_name ~* '%bar|baz%'; 因此,这个dbAction将返回一个action,我可以使用它来查询列表中包含某些名称部分的所有用户 所以 将返回一个操作,查询包含字符串“bar”或“baz”(不区分大小写)的所有姓氏。 我找到了一种查询单个模式的方法 val query = for { user
SELECT u.first_name, u.last_name
FROM users u
WHERE last_name ~* '%bar|baz%';
因此,这个dbAction将返回一个action,我可以使用它来查询列表中包含某些名称部分的所有用户
所以
将返回一个操作,查询包含字符串“bar”或“baz”(不区分大小写)的所有姓氏。
我找到了一种查询单个模式的方法
val query = for {
user <- users if user.lastName like "%bar%"
} yield (user.firstName, user.lastName)
由于这是一个不同的问题如何使用正则表达式,我为此创建了一个不同的问题:
只需组合这两个查询条件:
import slick.lifted.Tag
import slick.jdbc.H2Profile.api._
import scala.concurrent.duration._
import scala.concurrent.Await
object Test {
final case class User(firstName:String, lastName:String, id:Long = 0l)
class UserTable(tag: Tag) extends Table[User](tag, "user"){
def id = column[Long]("id", O.PrimaryKey, O.AutoInc)
def firstName = column[String]("first_name")
def lastName = column[String]("last_name")
def * = (firstName, lastName, id).mapTo[User]
}
def main(args:Array[String]):Unit = {
val db = Database.forConfig("h2config")
val users = TableQuery[UserTable]
val initialData = Seq(
User("Alex", "Arendar"),
User("David", "Arora"),
User("Dude", "Stoecki"),
User("Alexander", "the Great")
)
Await.result(
db.run(
users.schema.create andThen (users ++= initialData)
), 3 seconds
)
val query1 = for {
user <- users if user.firstName like "%Alex%"
} yield (user.firstName, user.lastName)
println(query1.result.statements.head)
println(Await.result(db.run(query1.result), 3 seconds))
val query2 = for {
user <- users if (user.firstName like "%Alex%") && user.firstName.inSet(Seq("Alex", "David"))
} yield (user.firstName, user.lastName)
println(query2.result.statements.head)
println(Await.result(db.run(query2.result), 3 seconds))
db.close()
}
正如您所看到的,生成的SQL确实包含like
和in
部分
我在这里使用内存H2数据库,但我认为这应该适用于任何RDBMS。只需结合这两个查询条件:
import slick.lifted.Tag
import slick.jdbc.H2Profile.api._
import scala.concurrent.duration._
import scala.concurrent.Await
object Test {
final case class User(firstName:String, lastName:String, id:Long = 0l)
class UserTable(tag: Tag) extends Table[User](tag, "user"){
def id = column[Long]("id", O.PrimaryKey, O.AutoInc)
def firstName = column[String]("first_name")
def lastName = column[String]("last_name")
def * = (firstName, lastName, id).mapTo[User]
}
def main(args:Array[String]):Unit = {
val db = Database.forConfig("h2config")
val users = TableQuery[UserTable]
val initialData = Seq(
User("Alex", "Arendar"),
User("David", "Arora"),
User("Dude", "Stoecki"),
User("Alexander", "the Great")
)
Await.result(
db.run(
users.schema.create andThen (users ++= initialData)
), 3 seconds
)
val query1 = for {
user <- users if user.firstName like "%Alex%"
} yield (user.firstName, user.lastName)
println(query1.result.statements.head)
println(Await.result(db.run(query1.result), 3 seconds))
val query2 = for {
user <- users if (user.firstName like "%Alex%") && user.firstName.inSet(Seq("Alex", "David"))
} yield (user.firstName, user.lastName)
println(query2.result.statements.head)
println(Await.result(db.run(query2.result), 3 seconds))
db.close()
}
正如您所看到的,生成的SQL确实包含like
和in
部分
我在这里使用了内存H2数据库,但我认为这将适用于任何RDBMS。查看您发布的代码,我认为您不需要将
中的与之类的进行文字组合。我把这个问题理解为想做一个正则表达式查询。尽管Slick不支持开箱即用的~*
操作符,但您可以自己添加它。这将为您提供一种使用Slick查询的提升嵌入式样式执行查询的方法
为此,可以使用SimpleExpression
builder。关于它的文档不多,但起点应该是参考手册的那一页
我们要做的是按照以下思路编写一个方法:
def find(names: Seq[String]): DBIO[Seq[String]] = {
val pattern = names.mkString("|")
users.filter(_.lastName regexLike pattern).map(_.lastName).result
}
要获得regexLike
,我们可以丰富(增强“pimp”)字符串列,以使用regexLike
方法:
implicit class RegexLikeOps(s: Rep[String]) {
def regexLike(p: Rep[String]): Rep[Boolean] = {
val expr = SimpleExpression.binary[String,String,Boolean] { (s, p, qb) =>
qb.expr(s)
qb.sqlBuilder += " ~* "
qb.expr(p)
}
expr.apply(s,p)
}
}
隐式类
部分允许编译器在任何时候都构造RegexLikeOps
类,只要它有一个Rep[String]
调用一个Rep[String]
还没有的方法(即,当要求regexLike
时)
我们的regexLike
方法采用另一个Rep[String]
参数作为模式,然后使用SimpleExpression
builder安全地构造我们想要使用的SQL
综合起来,我们可以写:
val program = for {
_ <- users.schema.create
_ <- users ++= User("foo") :: User("baz") :: User("bar") :: Nil
result <- find( Seq("baz","bar") )
} yield result
println( Await.result(db.run(program), 2.seconds) )
完整的代码是:查看您发布的代码,我认为您不需要将中的与类似的进行文字组合。我把这个问题理解为想做一个正则表达式查询。尽管Slick不支持开箱即用的~*
操作符,但您可以自己添加它。这将为您提供一种使用Slick查询的提升嵌入式样式执行查询的方法
为此,可以使用SimpleExpression
builder。关于它的文档不多,但起点应该是参考手册的那一页
我们要做的是按照以下思路编写一个方法:
def find(names: Seq[String]): DBIO[Seq[String]] = {
val pattern = names.mkString("|")
users.filter(_.lastName regexLike pattern).map(_.lastName).result
}
要获得regexLike
,我们可以丰富(增强“pimp”)字符串列,以使用regexLike
方法:
implicit class RegexLikeOps(s: Rep[String]) {
def regexLike(p: Rep[String]): Rep[Boolean] = {
val expr = SimpleExpression.binary[String,String,Boolean] { (s, p, qb) =>
qb.expr(s)
qb.sqlBuilder += " ~* "
qb.expr(p)
}
expr.apply(s,p)
}
}
隐式类
部分允许编译器在任何时候都构造RegexLikeOps
类,只要它有一个Rep[String]
调用一个Rep[String]
还没有的方法(即,当要求regexLike
时)
我们的regexLike
方法采用另一个Rep[String]
参数作为模式,然后使用SimpleExpression
builder安全地构造我们想要使用的SQL
综合起来,我们可以写:
val program = for {
_ <- users.schema.create
_ <- users ++= User("foo") :: User("baz") :: User("bar") :: Nil
result <- find( Seq("baz","bar") )
} yield result
println( Await.result(db.run(program), 2.seconds) )
完整代码是:如果(user.lastName类似“%bar%”)和user.lastName.inSet(Seq(“bar”、“baz”)
不起作用?查看生成的SQL语句会很有趣这不是我想要实现的。我希望获得与上面第一个代码部分中的sql语句相同的结果。如果(user.lastName类似“%bar%”)和user.lastName.inSet(Seq(“bar”,“baz”))不起作用,我将在编辑中添加插入的sql语句?查看生成的SQL语句会很有趣这不是我想要实现的。我希望获得与上面第一个代码部分中的sql语句相同的结果。我将在一个编辑器中添加插值sql语句。这不是我想要的。我有一个类似于Seq(“%le%”,%av%)的模式列表,并希望对该模式列表进行查询,而不是将类似SQL的语句与SQL-in语句连接起来。您的数据示例的结果将是Vector((亚历克斯,阿伦达),(“大卫”,“阿罗拉”),(亚历山大大帝))。谢谢你,这不是我想要的。我有一个类似于Seq(“%le%”,%av%)的模式列表,并希望对该模式列表进行查询,而不是将类似SQL的语句与SQL-in语句连接起来。您的数据示例的结果将是Vector((亚历克斯,阿伦达),(“大卫”,“阿罗拉”),(亚历山大大帝))。谢谢你,这就解决了我的问题。非常感谢。如果我看对了,你基本上可以创建任何类型的sql操作符,对吗?很酷的功能。@Stoecki是的,这是一个有用的功能。有点相关,如果你还没有看到,还有一个为Postgres添加了其他功能的功能。@RichardDallaway是的,我今天找到了这个存储库,但到目前为止没有深入研究它。但我会的。谢谢你指点。这解决了我的问题。非常感谢。如果我看对了,你基本上可以创建任何类型的sql操作符,对吗?很酷的功能。@Stoecki是的,这是一个有用的功能。有点相关,如果你还没有看到,还有一个为Postgres添加了其他功能的功能。@RichardDallaway是的,我今天找到了这个存储库,但到目前为止没有深入研究它。但我会的。谢谢你指点它。
val program = for {
_ <- users.schema.create
_ <- users ++= User("foo") :: User("baz") :: User("bar") :: Nil
result <- find( Seq("baz","bar") )
} yield result
println( Await.result(db.run(program), 2.seconds) )
select "last_name" from "app_user" where "last_name" ~* 'baz|bar'