1

我正在尝试使用 postgresql(数据库位于远程主机上)进行 csv 导入和导出数据。通常我会使用psql命令来做\copy <table> from <local path> ...\copy <table> to <local path> ...但我需要能够通过 Go 来做,因为我无法访问 shell 或没有安装 psql 的系统。

数据本身预计会很轻(可能< 2 MB 的数据一起),因此我试图不实现任何结构/模式来跟踪表中的列。导入数据库时​​,我想通过库/代码推断表的架构并将数据推送到表中。

关于如何实现这一点的任何建议?我不确定是否有任何 Go或database/sql允许此操作而无法指定列。对此有什么建议吗?pgxpq

编辑:

我最终使用https://github.com/joho/sqltocsv进行数据库导出,这非常简单,我不必定义任何架构/结构。

我没有代码,但我尝试gorm并意识到我需要为它定义一些结构/模式。

4

2 回答 2

3

我找到了使用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
}
于 2021-08-11T22:06:22.917 回答
3

签出此 pkg:https ://github.com/chop-dbhi/sql-importer

  1. 自动创建表
  2. 唯一性和非空检测。
  3. 支持超过 1600 列的 CSV 文件(Postgres 限制)
于 2021-08-09T09:13:15.763 回答