将数据导入 PostgreSQL 并导出为 CSV
import data into PostgreSQL and export to CSV
我正在尝试使用 postgresql(数据库位于远程主机)进行 csv 导入和导出数据。通常我会使用 psql
命令来执行 \copy <table> from <local path> ...
和 \copy <table> to <local path> ...
但我需要能够通过 Go 来完成它,而我无法访问 shell 或系统没有安装 psql。
数据本身应该很轻(加起来可能 < 2 MB 的数据),因此我尽量不实现任何 structs/schema 跟踪 table 中的列。导入数据库时,我想 library/code 推断 table 的模式并将数据推送到 tables.
关于如何实施这个有什么建议吗?我不确定是否有任何 Go database/sql
或 pgx
或 pq
允许这样做而无法指定列。对此有什么建议吗?
编辑:
我最终使用 https://github.com/joho/sqltocsv 进行数据库导出,这非常简单,我不必定义任何 schema/structs.
我没有代码,但我尝试了 gorm
并意识到我需要为其定义一些 struct/schema。
检查这个 pkg:https://github.com/chop-dbhi/sql-importer
- 自动table创建
- 唯一性和非空检测。
- 支持超过 1600 列(Postgres 限制)的 CSV 文件
我找到了使用 pgx
包的方法(感谢@Gustavo Kawamoto 的建议)。
这是我的导入和导出:
package main
import (
"fmt"
"os"
"github.com/jackc/pgx"
)
func main() {
pgxConConfig := pgx.ConnConfig{
Port: 5432,
Host: "remote_host",
Database: "db_name",
User: "my_user",
Password: "my_password",
}
conn, err := pgx.Connect(pgxConConfig)
if err != nil {
panic(err)
}
defer conn.Close()
tables := []string{"table1", "table2", "table3",}
import_dir := "/dir_to_import_from"
export_dir := "/dir_to_export_to"
for _, t := range tables {
f, err := os.OpenFile(fmt.Sprintf("%s/table_%s.csv", import_dir, t), os.O_RDONLY, 0777)
if err != nil {
return
}
f.Close()
err = importer(conn, f, t)
if err != nil {
break
}
fmt.Println(" Done with import and doing export")
ef, err := os.OpenFile(fmt.Sprintf("%s/table_%s.csv", export_dir, t), os.O_CREATE|os.O_WRONLY, 0777)
if err != nil {
fmt.Println("error opening file:", err)
return
}
ef.Close()
err = exporter(conn, ef, t)
if err != nil {
break
}
}
}
func importer(conn *pgx.Conn, f *os.File, table string) error {
res, err := conn.CopyFromReader(f, fmt.Sprintf("COPY %s FROM STDIN DELIMITER '|' CSV HEADER", table))
if err != nil {
return err
}
fmt.Println("==> import rows affected:", res.RowsAffected())
return nil
}
func exporter(conn *pgx.Conn, f *os.File, table string) error {
res, err := conn.CopyToWriter(f, fmt.Sprintf("COPY %s TO STDOUT DELIMITER '|' CSV HEADER", table))
if err != nil {
return fmt.Errorf("error exporting file: %+v", err)
}
fmt.Println("==> export rows affected:", res.RowsAffected())
return nil
}
我正在尝试使用 postgresql(数据库位于远程主机)进行 csv 导入和导出数据。通常我会使用 psql
命令来执行 \copy <table> from <local path> ...
和 \copy <table> to <local path> ...
但我需要能够通过 Go 来完成它,而我无法访问 shell 或系统没有安装 psql。
数据本身应该很轻(加起来可能 < 2 MB 的数据),因此我尽量不实现任何 structs/schema 跟踪 table 中的列。导入数据库时,我想 library/code 推断 table 的模式并将数据推送到 tables.
关于如何实施这个有什么建议吗?我不确定是否有任何 Go database/sql
或 pgx
或 pq
允许这样做而无法指定列。对此有什么建议吗?
编辑:
我最终使用 https://github.com/joho/sqltocsv 进行数据库导出,这非常简单,我不必定义任何 schema/structs.
我没有代码,但我尝试了 gorm
并意识到我需要为其定义一些 struct/schema。
检查这个 pkg:https://github.com/chop-dbhi/sql-importer
- 自动table创建
- 唯一性和非空检测。
- 支持超过 1600 列(Postgres 限制)的 CSV 文件
我找到了使用 pgx
包的方法(感谢@Gustavo Kawamoto 的建议)。
这是我的导入和导出:
package main
import (
"fmt"
"os"
"github.com/jackc/pgx"
)
func main() {
pgxConConfig := pgx.ConnConfig{
Port: 5432,
Host: "remote_host",
Database: "db_name",
User: "my_user",
Password: "my_password",
}
conn, err := pgx.Connect(pgxConConfig)
if err != nil {
panic(err)
}
defer conn.Close()
tables := []string{"table1", "table2", "table3",}
import_dir := "/dir_to_import_from"
export_dir := "/dir_to_export_to"
for _, t := range tables {
f, err := os.OpenFile(fmt.Sprintf("%s/table_%s.csv", import_dir, t), os.O_RDONLY, 0777)
if err != nil {
return
}
f.Close()
err = importer(conn, f, t)
if err != nil {
break
}
fmt.Println(" Done with import and doing export")
ef, err := os.OpenFile(fmt.Sprintf("%s/table_%s.csv", export_dir, t), os.O_CREATE|os.O_WRONLY, 0777)
if err != nil {
fmt.Println("error opening file:", err)
return
}
ef.Close()
err = exporter(conn, ef, t)
if err != nil {
break
}
}
}
func importer(conn *pgx.Conn, f *os.File, table string) error {
res, err := conn.CopyFromReader(f, fmt.Sprintf("COPY %s FROM STDIN DELIMITER '|' CSV HEADER", table))
if err != nil {
return err
}
fmt.Println("==> import rows affected:", res.RowsAffected())
return nil
}
func exporter(conn *pgx.Conn, f *os.File, table string) error {
res, err := conn.CopyToWriter(f, fmt.Sprintf("COPY %s TO STDOUT DELIMITER '|' CSV HEADER", table))
if err != nil {
return fmt.Errorf("error exporting file: %+v", err)
}
fmt.Println("==> export rows affected:", res.RowsAffected())
return nil
}