2015-11-08 74 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