26

anorm で「in」句を使用するのは簡単な方法ではないようです。

val ids = List("111", "222", "333")
val users = SQL("select * from users where id in ({ids})").on('ids-> ???).as(parser *)

部品の交換方法は???

私は試した:

on('ids -> ids)
on('ids -> ids.mkString("'","','","'"))
on('ids -> ids.mkString("','")

しかし、どれも機能しません。

ディスカッションでまったく同じ問題が見られます: https://groups.google.com/d/topic/play-framework/qls6dhhdayc/discussion、著者には複雑な解決策があります:

val params = List(1, 2, 3) 

val paramsList = for ( i <- 0 until params.size ) yield ("userId" + i) 

// ---> results in List("userId0", "userId1", "userId2") 

User.find("id in ({%s})"

    // produces "id in ({userId0},{userId1},{userId2})"
    .format(paramsList.mkString("},{")) 

    // produces Map("userId0" -> 1, "userId1" -> 2, ...) 
    .on(paramsList.zip(params))
    .list() 

これは複雑すぎる。

もっと簡単な方法はありますか?それとも、簡単にするために何かを提供する必要がありますか?

4

7 に答える 7

8

ばっちり成功!このスレッドにはこれ以上の更新はありませんが、まだ関連しているようです. そういうわけで、そして答えがないので、私は私のものを投げ入れて検討しようと思いました.

Anorm は 'IN' 句をサポートしていません。私は彼らがそうするだろうとは思わない. それらを機能させるためにできることは何もありません.Anormを「ORMのように」感じさせたので、anormがこれらの句を具体的に削除した投稿を読んだことさえあります.

ただし、IN 句をサポートする短いクラスで SqlQuery をラップし、必要に応じてそのクラスを SqlQuery に変換するのはかなり簡単です。

少し長くなるので、ここにコードを貼り付ける代わりに、コードとその使用方法を投稿したブログへのリンクをここに示します。

Anormとの節

基本的に、私のブログからコードを取得すると、ステートメントは次のようになります。

RichSQL(""" SELECT * FROM users WHERE id IN ({userIds}) """).onList("userIds" -> userIds).toSQL.as(userParser *)(connection)
于 2013-04-17T22:03:45.967 に答える
1

おそらく遅いですが、同じものを探している他の人のためにこれを追加します。これを克服するために、いくつかの組み込みデータベース機能を使用できます。これは、ORM に対する Anorm の利点の 1 つです。たとえば、PostgreSQL を使用している場合、リストを配列として渡し、クエリで配列のネストを解除できます。

IDは整数であると仮定します。

val ids = List(1, 2, 3)

val idsPgArray = "{%s}".format(ids.mkString(",")) //Outputs {1, 2, 3}

val users = SQL(
  """select * from users where id in (select unnest({idsPgArray}::integer[]))"""
).on('ids-> ???).as(parser *)

実行されたクエリは

select * from users where id in (select unnest('{1, 2, 3}'::integer[])) 

に等しい

select * from users where id in (1, 2, 3)
于 2013-12-06T17:51:34.930 に答える
0

私は最近同じ問題を抱えていました。残念ながら、文字列補間を使用せずに SQL インジェクションに対して脆弱な方法はないようです。

私がやったことは、それをintのリストに変換して元に戻すことで、ちょっとサニタイズすることでした:

val input = "1,2,3,4,5"

// here there will be an exception if someone is trying to sql-inject you
val list = (_ids.split(",") map Integer.parseInt).toList

// re-create the "in" string
SQL("select * from foo where foo.id in (%s)" format list.mkString(","))
于 2012-11-20T23:38:07.877 に答える
-1
val ids = List("111", "222", "333")
val users = SQL("select * from users 
                 where id in 
                 (" +  ids.reduceLeft((acc, s) => acc + "," + s) + ")").as(parser *)
于 2012-07-25T13:01:46.397 に答える
-1
User.find("id in (%s)"
  .format(params.map("'%s'".format(_)).mkString(",") )
  .list() 
于 2012-07-24T20:19:39.913 に答える