我有一个返回大量行的 sql 查询。我想将查询结果保存到磁盘上的 csv 文件中。但是,因为有太多行,所以在 sql 查询可以聚合所有行之前,我的内存不足。
它看起来像这样,并且在查询部分失败:
(-> query format-transformer csv-writer)
Run Code Online (Sandbox Code Playgroud)
我在#clojure irc 频道的帮助下弄明白了。你需要两个库:
(ns myproj.example
(:require [[clojure.java.jdbc :as sql]
[clojure.data.csv :as csv]]))
Run Code Online (Sandbox Code Playgroud)
诀窍是在返回时处理每一行,然后将其丢弃。java jdbc 库具有查询功能,该功能使用:row-fn和:result-set-fn选项提供此功能。
(defn sql->csv [title]
(with-open [w (clojure.java.io/writer (str title ".csv") :append true)]
(sql/query ds (second query)
:row-fn (fn [row]
(csv/write-csv w [(mapv str (vals row))]))
:result-set-fn dorun)))
Run Code Online (Sandbox Code Playgroud)
有趣的部分是:row-fn和:result-set-fn。
该:row-fn分派每一个行从查询返回的时间。每一行都是表格中的一张地图{:column1 "data" :column2 "data2"}。我们改变地图到的东西,写的csv可以使用(嵌套向量)与此:[(mapv str (:vals row)])。然后 write-csv 将其附加到您提供的文件中。
这:result-set-fn对于不炸毁堆至关重要。通过将其设置为dorun您告诉它在处理时丢弃头部。
这个特定的实现不提供列标题,这是留给读者的练习(我的太尴尬了,无法在公共论坛上发布)。
| 归档时间: |
|
| 查看次数: |
552 次 |
| 最近记录: |