如何将行从 STDIN 导入 Postgresql?

在 Python 中,我有以下内容可以在不使用文件的情况下将行批量加载到 Postgresql:


import csv

import subprocess


mylist, keys = [{'name': 'fred'}, {'name': 'mary'}], ['name']

p = subprocess.Popen(['psql', 'mydb', '-U', 'openupitsme', '-h', 'my.ip.address', '--no-password', '-c',

    '\COPY tester(%s) FROM STDIN (FORMAT CSV)' % ', '.join(keys),

    '--set=ON_ERROR_STOP=false'

    ], stdin=subprocess.PIPE

)

for d in mylist:

    dict_writer = csv.DictWriter(p.stdin, keys, quoting=csv.QUOTE_MINIMAL)

    dict_writer.writerow(d)

p.stdin.close()

我试图在 Go 中完成同样的事情。我目前正在将行写入文件,然后导入它们,然后删除该文件。我想像在 Python 中一样从 STDIN 导入行。我有:


package main


import (

    "database/sql"

    "log"

    "os"

    "os/exec"


    _ "github.com/lib/pq"

)


var (

    err error

    db  *sql.DB

)


func main() {

    var err error

    fh := "/path/to/my/file.txt"

    f, err := os.Create(fh)

    if err != nil {

        panic(err)

    }

    defer f.Close()

    defer os.Remove(fh)

    rows := []string{"fred", "mary"}

    for _, n := range rows {

        _, err = f.WriteString(n + "\n")

        if err != nil {

            panic(err)

        }

    }

    // dump to postgresql

    c := exec.Command("psql", "mydb", "-U", "openupitsme", "-h", "my.ip.address", "--no-password",

        "-c", `\COPY tester(customer) FROM `+fh)

    if out, err := c.CombinedOutput(); err != nil {

        log.Println(string(out), err)

    }

}


江户川乱折腾
浏览 237回答 2
2回答

摇曳的蔷薇

该github.com/lib/pq包的文档实际上有一个例子,如何做你想做的。这是整个程序的改编文本:package mainimport (    "database/sql"    "log"    "github.com/lib/pq")func main() {    records := [][]string{        {"Rob", "Pike"},        {"Ken", "Thompson"},        {"Robert", "Griesemer"},    }    db, err := sql.Open("postgres", "dbname=postgres user=postgres password=postgres")    if err != nil {        log.Fatalf("open: %v", err)    }    if err = db.Ping(); err != nil {        log.Fatalf("open ping: %v", err)    }    defer db.Close()    txn, err := db.Begin()    if err != nil {        log.Fatalf("begin: %v", err)    }    stmt, err := txn.Prepare(pq.CopyIn("test", "first_name", "last_name"))    if err != nil {        log.Fatalf("prepare: %v", err)    }    for _, r := range records {        _, err = stmt.Exec(r[0], r[1])        if err != nil {            log.Fatalf("exec: %v", err)        }    }    _, err = stmt.Exec()    if err != nil {        log.Fatalf("exec: %v", err)    }    err = stmt.Close()    if err != nil {        log.Fatalf("stmt close: %v", err)    }    err = txn.Commit()    if err != nil {        log.Fatalf("commit: %v", err)    }}在我的机器上,这会在大约 2 秒内导入 1 000 000 条记录。

DIEA

下面的代码应该指向你想要去的方向:package mainimport (&nbsp; &nbsp; "fmt"&nbsp; &nbsp; "log"&nbsp; &nbsp; "os"&nbsp; &nbsp; "os/exec"&nbsp; &nbsp; "strings")func main() {&nbsp; &nbsp; keys := []string{"customer"}&nbsp; &nbsp; sqlCmd := fmt.Sprintf("COPY tester(%s) FROM STDIN (FORMAT CSV)", strings.Join(keys, ","))&nbsp; &nbsp; cmd := exec.Command("psql", "<dbname>", "-U", "<username>", "-h", "<host_ip>", "--no-password", "-c", sqlCmd)&nbsp; &nbsp; cmd.Stdin = os.Stdin&nbsp; &nbsp; output, _ := cmd.CombinedOutput()&nbsp; &nbsp; log.Println(string(output))}如果密钥需要是动态的,您可以从os.Args.请注意,如果您打算使用 psql 命令,那么您不需要导入 database/sql 或 lib/pq。如果您对使用 lib/pq 感兴趣,请查看lib/pq 文档中的批量导入。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go