CSV导入PostgreSQL的Clojure脚本问题(已更新)
问题排查与优化方案
一、第一个错误:未知SQL子句(:ID, :BILLINGLONGITUDE等)
问题根源
你的h/values调用传参错误:big-map本身是多个map组成的序列(每条记录对应一个map),但你用[big-map]把整个序列又包了一层数组,导致Honey SQL误将每个map的key(如:ID)识别为SQL子句,而非字段名。
修复代码
把插入代码里的[big-map]改成直接传big-map:
(-> (h/insert-into :account) (h/values big-map) ;; 去掉外层[] (sql/format {:pretty true}))
二、第二个错误:relation "account" does not exist
可能原因及排查步骤
表名大小写问题:PostgreSQL默认会把未加引号的标识符转为小写,如果原库表名是驼峰(如
Account)或大写(如ACCOUNT),直接用:account会找不到表。- 修复:用
sql/quoted保留原表名大小写:
或者直接使用带引号的字符串:(h/insert-into (sql/quoted :Account)) ;; 对应原库的Account表(h/insert-into "\"Account\"")
- 修复:用
Schema未指定:如果表不在默认的
publicschema下,需要明确指定schema:(h/insert-into :my_schema/account) ;; my_schema是实际schema名连接权限验证:确认数据库用户有权限访问目标表,可先在REPL执行简单查询验证:
(jdbc/execute! db-spec ["SELECT * FROM account LIMIT 1"])(替换
db-spec为你的数据库连接配置)
三、整体优化方案
1. 数据预处理
CSV中可能存在空字符串(如:BILLINGLONGITUDE ""),若PostgreSQL对应字段为数值类型会插入失败,建议提前转换空值为nil:
(defn csv-data->map [csv-data] (map (fn [row] (into {} (map (fn [[k v]] [k (if (empty? v) nil v)])) (zipmap (->> (first csv-data) (map keyword)) row))) (rest csv-data)))
2. 批量插入优化
数据量较大时,一次性插入所有记录会影响性能,建议分批次插入:
(defn batch-insert [db-spec table rows batch-size] (doseq [batch (partition-all batch-size rows)] (let [sql (-> (h/insert-into table) (h/values batch) (sql/format))] (jdbc/execute! db-spec sql)))) ;; 使用示例:每1000条记录插一次 (batch-insert db-spec :account big-map 1000)
3. 日志与调试
插入前格式化SQL并打印,确认生成的语句符合预期:
(def insert-sql (-> (h/insert-into :account) (h/values (take 1 big-map)) ;; 只取第一条测试 (sql/format {:pretty true}))) (println insert-sql)
内容的提问来源于stack exchange,提问作者tsakishii
相关产品推荐
相关产品推荐

