PostgreSQL的“COPY table FROM file”语句可以在Go中使用吗?

Posted

技术标签:

【中文标题】PostgreSQL的“COPY table FROM file”语句可以在Go中使用吗?【英文标题】:Can PostgreSQL's "COPY table FROM file" statement be used in Go? 【发布时间】:2015-10-19 00:22:45 【问题描述】:

阅读 github.com/lib/pq 文档后,我仍然不清楚是否可以使用简单的 COPY <table> FROM <file> CSV HEADER 命令从 CSV 文件中复制数据。

这就是我想要做的:

func CopyFromCSV(con Con, tableName, fileName string) error 
    _, err := con.Exec(fmt.Sprintf("TRUNCATE %s", tableName))
    if err != nil 
        return err
    

    stm, err := con.Prepare(fmt.Sprintf("COPY %s FROM '%s' CSV HEADER", tableName, fileName))
    if err != nil 
        return err
    
    defer stm.Close()

    _, err = stm.Exec()
    return err

其中tableName 是现有表,fileName 是现有 csv 文件的绝对路径。

con.Prepare 调用后我总是收到以下错误:pq: unknown response for copy query: 'C'

是否可以在 Go 中使用 github.com/lib/pq 驱动程序通过 postgres 数据库执行此操作?

【问题讨论】:

尝试在psql命令行客户端执行同样的命令。 它按预期工作:# COPY <table> FROM '/home/path/to/file.csv' CSV HEADER;COPY 1773 COPY 功能不受pq 驱动程序的完全支持:github.com/lib/pq/issues/213。在保持与数据库/sql API 兼容的同时,使用COPY 似乎存在问题。如果您不需要符合 database/sql,您可能可以使用另一个驱动程序。 另请注意,COPY … FROMCOPY … TO 语句从服务器上的文件复制/复制到文件。如果您想在客户端上使用文件,您至少需要使用COPY…FROM STDIN(或COPY…TO STDOUT)并自己进行文件操作(这也是psql\copy 命令所做的)。如前所述,这不适合database/sql API,所以如果驱动程序支持它,我非常怀疑它会通过PrepareExec 它应该适用于服务器端路径。如果没有,那么驱动程序真的很不完整,因为使用服务器端路径的 COPY 非常简单。不过,支持COPY ... FROM stdinTO stdout(用于客户端文件)要复杂得多。 【参考方案1】:

可以在此处找到执行 COPY 命令的粗略模板 - https://play.golang.org/p/6y5v3IW8kD

下面的代码应该适合你。

   func copyTest() 

    psqlInfo := fmt.Sprintf("host=%s port=%d user=%s password=%s dbname=%s sslmode=verify-full",host, port, user, password, dbname)
    db, err := sql.Open("postgres", psqlInfo)
    if err != nil 
        panic(err)
    
    defer db.Close()

    err = db.Ping()
    if err != nil 
        panic(err)
    


    tx, err := db.Begin()
    if err != nil 
        panic(err)
    

    _, err = tx.Exec("copy metadata.charvalues_temp from 'C:\\yourlocation\\yourfile.csv' with csv")
    if err != nil 
        panic(err)
    
    err = tx.Commit()
    if err != nil 
        panic(err)
    

【讨论】:

【参考方案2】:

下面的代码使用https://github.com/lib/pq

    import (
        "database/sql"
        "fmt"
        "github.com/lib/pq"
    )

func bulkCopyTest() 
    psqlInfo := fmt.Sprintf("host=%s port=%d user=%s password=%s dbname=%s sslmode=verify-full",
        host, port, user, password, dbname)
    db, err := sql.Open("postgres", psqlInfo)
    if err != nil 
        panic(err)
    
    defer db.Close()

    tx, err := db.Begin()

    if err != nil 
        panic(err)
    

    stmt, err := tx.Prepare(pq.CopyInSchema("schemaName", "DBName", "columnName", "columnName"))
    if err != nil 
        panic(err)
    

    //loop through an array of struct filled with data, or read from a file
    for _, row := range loadCsv 
        stmt.Exec(row.value1, row.value2)
        if err != nil 
            panic(err)
        
    

    _, err = stmt.Exec()
    if err != nil 
        panic(err)
    
    err = stmt.Close()
    if err != nil 
        panic(err)
    
    err = tx.Commit()
    if err != nil 
        panic(err)
    

【讨论】:

以上是关于PostgreSQL的“COPY table FROM file”语句可以在Go中使用吗?的主要内容,如果未能解决你的问题,请参考以下文章

PostgreSQL介绍以及如何开发框架中使用PostgreSQL数据库

mac默认安装postgresql, 如何让postgresql可以远程访问

Wix,PostgreSQL 安装,执行 Postgresql 脚本

[PostgreSQL] 图解安装 PostgreSQL

PostgreSQL | Arch Linux安装PostgreSQL

prometheus使用postgresql-adapter连接postgresql