2015-11-08 39 views
2

我正在连接到PostgreSQL数据库,我想知道在某些UUID类型的列中是否存在uuid表。参数uuid在另一个函数中生成。 Clojure中我尝试使用clojure.java.jdbc/db-do-prepared检查PostgreSQL表中是否存在uuid

(jdbc/db-do-prepared {:datasource datasource} 
      "SELECT exists (SELECT 1 FROM account WHERE guid=?::uuid)" 
      [uuid]) 

但它抛出一个异常:

BatchUpdateException Batch entry 0 SELECT exists (SELECT 1 FROM table WHERE guid='dbe8cda5-d37c-3446-9b9c-85e0344af3b1'::uuid) was aborted. Call getNextException to see the cause. org.postgresql.jdbc2.AbstractJdbc2Statement$BatchResultHandler.handleError (AbstractJdbc2Statement.java:2781) 

如果我连接到数据库,并粘贴生成的SQL并执行它,它工作正常。从project.clj

(jdbc/db-do-prepared {:datasource datasource} 
        "INSERT INTO table(guid) VALUES (?::uuid)" 
        [uuid]) 

相关的依赖关系:

[org.clojure/java.jdbc "0.4.2"] 
[org.postgresql/postgresql "9.4-1205-jdbc42"] 
[hikari-cp "1.3.1"] 

回答

1

do-prepared文档:

返回更新计数的序列我还可以从Clojure的使用下面的代码插入(每个参数组一个计数)

UPDATEDELETE是返回更新计数的唯一SQL CRUD操作。所以do-prepared只能与那些一起使用。但是,有更直接的抽象:对于UPDATE使用update!和对DELETE使用delete!

INSERT返回生成的密钥,并可以与do-prepared一起返回插入计数。但是,这样你就无法获得生成的主键的值。使用do-prepared-return-keys,或更好的,直接抽象insert!

SELECT回归的结果集,而不是更新计数,且不会do-prepared工作。

如果你想使用批处理SELECT s的一份声明中,这样做的:

  • 结合使用with-db-connection
  • 该连接上创建一个准备好的声明,并将其绑定到一个单一的数据库连接VAR
  • 使用查询功能指引两者绑定连接,并事先准备好的声明

像这样:

(j/with-db-connection [c datasource] 
     (let [ps (j/prepare-statement (j/get-connection c) 
       "SELECT count(*) from person where left(name,1)=?")] 
     (doall (map #(j/query c [ps %]) ["a" "b" "c"])))) 

尽管我最初认为数据库能够通过参数化优化查询,但进一步的测试表明,这可以使查询速度提高60%。大部分加速都在数据库端,因为语句准备开销可以忽略不计。该测试使用与OP提到的相同的用例,检查UUID(从1K到100K)。

使用准备好的语句的通用版本可以清理一个小宏幻成以下几点:

(defmacro with-prepared-statement 
    [[connection-bind datasource 
    statement-bind sql & keys] 
    & body] 
    `(clojure.java.jdbc/with-db-connection [~connection-bind datasource] 
             (let [~statement-bind (apply clojure.java.jdbc/prepare-statement 
                     (clojure.java.jdbc/get-connection datasource) ~sql ~keys)] 
              [email protected]))) 

(with-prepared-statement [c datasource 
          ps "SELECT count(*) from persoon where left(voornaam,1)=?"] 
         (doall (map #(j/query c [ps %]) ["a" "b" "c"]))) 
+0

啊,是的!我最初使用'插入!'做插入,但是会导致一个转换异常,因此在这种情况下使用'do-prepared'。在我原来的问题'SELECT'与'query'一起工作。感谢您的额外信息,我一定会牢记以备将来参考。 – Joel