2
(sql/with-connection {... mydatabase }
    (sql/with-query-results rows [ "select * from users where email in (?)" 
       [ "bob@site.com" "mary@other.com" ] ] 
       (doseq [rows row] 
            (prn row))))

这将始终不返回任何结果。我也试过只使用“?” 代替“(?)”

4

2 回答 2

2

AFAIR 你不能直接这样做。幕后宏with-query-results使用 java.sql.PreparedStatement 并为每个参数调用 .setObject。所以你必须写这样的东西

(sql/with-connection db
  (sql/with-query-results rs
    [(str "select * from users where email in ("
          (apply
           str
           (interpose ", " (map #(str "\"" % "\"")
                                ["bob@site.com" "mary@other.com"]))) ")")]
    ...))

使用“in”参数生成已经准备好的 sql 字符串:"select * from users where email in (\"bob@site.com\", \"mary@other.com\")".

更好的方法是使用 clojure sql 库之一,如 sqlkorma。

于 2012-12-18T07:17:51.007 回答
0

现在在 2020 年,您可以在没有字符串连接的情况下执行此操作,至少在 postgres 中是这样。

像这样扩展 ISQLParameter 协议:

; This allows us to use clojure arrays as query parameters for JDBC.
; Thus, we don't need to do string concatenation to make IN clauses.
(extend-protocol clojure.java.jdbc/ISQLParameter
  Sequential
  ; Important: Sometimes you have to explicitly specify the type of array like ?::text[].
  (set-parameter [v ^PreparedStatement stmt ^long i]
    (let [conn (.getConnection stmt)
          meta (.getParameterMetaData stmt)
          type-name (.getParameterTypeName meta i)]
      (if-let [elem-type (when (= (first type-name) \_) (apply str (rest type-name)))]
        (.setObject stmt i (.createArrayOf conn elem-type (to-array v)))
        (.setObject stmt i v)))))

然后你可以运行像这样的查询

(jdbc/query db/db ["select 'banana' = ANY(?) as banana_included, 
                           'apple' = ANY(?) as apple_included" 
                   ["banana" "potato"] ["banana" "potato"]])

= ANY(array)语法与子句的作用相同——in据我所知,IN子句在 postgres 中被转换为= ANY(array)内部的——不过不要引用我的话。

于 2020-03-30T12:09:11.330 回答