在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) } }
编辑:进一步,但这不是插入记录:
keys := []string{"link", "domain"} records := [][]string{ {"first_name", "last_name"}, {"Rob", "Pike"}, {"Ken", "Thompson"}, {"Robert", "Griesemer"}, } cmd := exec.Command("psql") stdin, err := cmd.StdinPipe() if err != nil { log.Println(err) } stdout, err := cmd.StdoutPipe() if err != nil { log.Println(err) } if err := cmd.Start(); err != nil { log.Println(err) } go func() { _, err = io.WriteString(stdin, "search -U meyo -h 1.2.3.4 -p 1111 --no-password -c ") if err != nil { log.Println(err) } _, err := io.WriteString(stdin, fmt.Sprintf("COPY links(%s) FROM STDIN (FORMAT CSV)", strings.Join(keys, ","))) if err != nil { log.Println(err) } w := csv.NewWriter(stdin) if err := w.WriteAll(records); err != nil { log.Fatalln("error writing record to csv:", err) } w.Flush() if err := w.Error(); err != nil { log.Fatal(err) } if err != nil { log.Println(err) } stdin.Close() }() done := make(chan bool) go func() { _, err := io.Copy(os.Stdout, stdout) if err != nil { log.Fatal(err) } stdout.Close() done <- true }() <-done if err := cmd.Wait(); err != nil { log.Println(err, cmd.Args, stdout) }
没有插入任何记录,并且出现无用的错误:
exit status 2
下面的代码应指导您要走的方向:
package main import ( "fmt" "log" "os" "os/exec" "strings" ) func main() { keys := []string{"customer"} sqlCmd := fmt.Sprintf("COPY tester(%s) FROM STDIN (FORMAT CSV)", strings.Join(keys, ",")) cmd := exec.Command("psql", "<dbname>", "-U", "<username>", "-h", "<host_ip>", "--no-password", "-c", sqlCmd) cmd.Stdin = os.Stdin output, _ := cmd.CombinedOutput() log.Println(string(output)) }
如果密钥需要动态,则可以从中获取密钥os.Args。
os.Args
请注意,如果您打算使用psql命令,则不需要导入数据库/ sql或lib / pq。如果您对使用lib / pq感兴趣,请参阅lib / pq文档中的Bulk Imports。