我正在连接到PostgreSQL数据库,我想知道某个表中的UUID类型列中是否存在uuid。参数uuid在另一个函数中生成。 在clojure中我尝试
(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并执行它,它可以正常工作。我也可以使用以下代码从clojure插入:
(jdbc/db-do-prepared {:datasource datasource}
"INSERT INTO table(guid) VALUES (?::uuid)"
[uuid])
来自project.clj的相关依赖项:
[org.clojure/java.jdbc "0.4.2"]
[org.postgresql/postgresql "9.4-1205-jdbc42"]
[hikari-cp "1.3.1"]
答案 0 :(得分:1)
来自do-prepared
的文档:
返回一系列更新计数(每个参数组一个计数)
UPDATE
和DELETE
是唯一返回更新计数的SQL CRUD操作。所以do-prepared
应该只与那些一起使用。但是,还有更多直接抽象:UPDATE
使用update!
和DELETE
使用delete!
。
INSERT
返回生成的密钥,可以使用do-prepared
返回插入计数。但是,这样您就无法获得生成的主键的值。使用do-prepared-return-keys
或更好的直接抽象insert!
SELECT
返回结果集,而不是更新计数,并且无法使用do-prepared
。
如果您确实希望将批处理SELECT
与预准备语句一起使用,请执行以下操作:
with-db-connection
像这样:
(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)]
~@body)))
(with-prepared-statement [c datasource
ps "SELECT count(*) from persoon where left(voornaam,1)=?"]
(doall (map #(j/query c [ps %]) ["a" "b" "c"])))