如何使用 clojure.java.jdbc 进行 UPSERT

Posted

技术标签:

【中文标题】如何使用 clojure.java.jdbc 进行 UPSERT【英文标题】:How to UPSERT with clojure.java.jdbc 【发布时间】:2021-02-25 18:07:08 【问题描述】:

我使用插入多!在 clojure.java.jdbc 中将多行插入到 Postgresql 表中。出于某种原因,我在要插入的行中得到了重复的主键。这些必须被忽略,其余的必须正常插入。所以我需要使用 ON CONFLICT DO NOTHING 语法“更新”。这是clojure.java.jdbc的使用方法:

(jdbc/insert-multi! db-spec :fruit
                [:name :cost]
                [["Pomegranate" 585] 
                 ["Kiwifruit" 93]])

但实际上我必须执行以下操作:

INSERT INTO fruit (name, cost)
VALUES ("Pomegranate", 585), 
       ("Kiwifruit", 93) 
ON CONFLICT (name) DO NOTHING;

是否有任何解决方法?我应该自己准备在字符串中插入查询吗?

【问题讨论】:

请分享您的表格结构 【参考方案1】:

您可能会发现 HoneySQL 很有帮助,因为它支持更复杂的 INSERT 语句并生成可与 jdbc/execute! 一起使用的 SQL 字符串 + 参数向量:

https://cljdoc.org/d/seancorfield/honeysql/2.0.0-alpha2/doc/getting-started/postgresql-support

【讨论】:

HoneySQL,一种更高级别的 DSL。在clojure.java.jdbc的概述中介绍过。谢谢你,肖恩。干得好!【参考方案2】:

您可以将 HoneySQL 与 HoneySQL PostgreSQL helpers 一起使用以使用 upsert (ON CONFLICT DO ...):

(require '[honeysql-postgres.helpers :as sql.helpers])

(-> (insert-into :fruit)
    (values [:cost 585 :name "Pomegrenade"
             :cost 93 :name "Kiwifruit"])
    (sql.helpers/upsert (-> (sql.helpers/on-conflict :name)
                            (sql.helpers/do-nothing)))
    (sql.helpers/returning :*)
    sql.helpers/format)
=> ["INSERT INTO distributors (cost, name) VALUES (?, ?), (?, ?) ON CONFLICT (name) DO NOTHING RETURNING *" 
    585 "Pomegrenade" 
    93 "Kiwifruit"]

【讨论】:

以上是关于如何使用 clojure.java.jdbc 进行 UPSERT的主要内容,如果未能解决你的问题,请参考以下文章

如何做批处理 jdbc/insert!和 jdbc/更新!在 Clojure 中使用 postgresql?

java.jdbc clojure 执行!插入数量

使用clojure.java.jdbc在Clojure中使用外键约束

clojure.java.jdbc 更新 id 在哪里

Clojure jdbc 创建复合主键

clojure.java.jdbc /查询大结果集懒惰