使用 pgx 在 GO 中的 Postgres 中批量插入
Bulk INSERT in Postgres in GO using pgx
我正在尝试在数据库中批量插入键,这里是代码
关键结构
type tempKey struct {
keyVal string
lastKey int
}
测试键
data := []tempKey{
{keyVal: "abc", lastKey: 10},
{keyVal: "dns", lastKey: 11},
{keyVal: "qwe", lastKey: 12},
{keyVal: "dss", lastKey: 13},
{keyVal: "xcmk", lastKey: 14},
}
插入部分
dbUrl := "db url...."
conn, err := pgx.Connect(context.Background(), dbUrl)
if err != nil {
println("Errrorr...")
}
defer conn.Close(context.Background())
sqlStr := "INSERT INTO keys (keyval,lastval) VALUES "
dollars := ""
vals := []interface{}{}
count := 1
for _, row := range data {
dollars = fmt.Sprintf("%s($%d, $%d),", dollars, count, count+1)
vals = append(vals, row.keyVal, row.lastKey)
count += 2
}
sqlStr += dollars
sqlStr = sqlStr[0 : len(sqlStr)-1]
fmt.Printf("%s \n", sqlStr)
_, erro := conn.Exec(context.Background(), sqlStr, vals)
if erro != nil {
fmt.Fprint(os.Stderr, "Error : \n", erro)
}
在 运行 上它抛出错误:需要 10 个参数,得到 1
批量插入的正确方法是什么
使用批次(https://github.com/jackc/pgx/blob/master/batch_test.go):
batch := &pgx.Batch{}
batch.Queue("insert into ledger(description, amount) values(, )", "q1", 1)
batch.Queue("insert into ledger(description, amount) values(, )", "q2", 2)
br := conn.SendBatch(context.Background(), batch)
您正在手工制作 SQL 语句,这很好,但是您没有利用 pgx
来帮助解决这个问题(见下文)。
像这样附加到 SQL 字符串对于大输入可能效率低下
dollars = fmt.Sprintf("%s($%d, $%d),", dollars, count, count+1)
但最终值也有一个尾随 ,
,而您需要一个终止字符 ;
来指示语句的结尾。
顺便说一句,这个字符串截断行是多余的:
sqlStr = sqlStr[0 : len(sqlStr)-1] // this is a NOOP
无论如何,在制作长字符串时最好使用 strings.Builder 等性能更高的东西。
从 pgx
文档中,使用 pgx.Conn.CopyFrom:
func (c *Conn) CopyFrom(tableName Identifier, columnNames []string, rowSrc CopyFromSource) (int, error)
CopyFrom uses the PostgreSQL copy protocol to perform bulk data
insertion. It returns the number of rows copied and an error.
example usage 副本:
rows := [][]interface{}{
{"John", "Smith", int32(36)},
{"Jane", "Doe", int32(29)},
}
copyCount, err := conn.CopyFrom(
pgx.Identifier{"people"},
[]string{"first_name", "last_name", "age"},
pgx.CopyFromRows(rows),
)
我正在尝试在数据库中批量插入键,这里是代码 关键结构
type tempKey struct {
keyVal string
lastKey int
}
测试键
data := []tempKey{
{keyVal: "abc", lastKey: 10},
{keyVal: "dns", lastKey: 11},
{keyVal: "qwe", lastKey: 12},
{keyVal: "dss", lastKey: 13},
{keyVal: "xcmk", lastKey: 14},
}
插入部分
dbUrl := "db url...."
conn, err := pgx.Connect(context.Background(), dbUrl)
if err != nil {
println("Errrorr...")
}
defer conn.Close(context.Background())
sqlStr := "INSERT INTO keys (keyval,lastval) VALUES "
dollars := ""
vals := []interface{}{}
count := 1
for _, row := range data {
dollars = fmt.Sprintf("%s($%d, $%d),", dollars, count, count+1)
vals = append(vals, row.keyVal, row.lastKey)
count += 2
}
sqlStr += dollars
sqlStr = sqlStr[0 : len(sqlStr)-1]
fmt.Printf("%s \n", sqlStr)
_, erro := conn.Exec(context.Background(), sqlStr, vals)
if erro != nil {
fmt.Fprint(os.Stderr, "Error : \n", erro)
}
在 运行 上它抛出错误:需要 10 个参数,得到 1
批量插入的正确方法是什么
使用批次(https://github.com/jackc/pgx/blob/master/batch_test.go):
batch := &pgx.Batch{}
batch.Queue("insert into ledger(description, amount) values(, )", "q1", 1)
batch.Queue("insert into ledger(description, amount) values(, )", "q2", 2)
br := conn.SendBatch(context.Background(), batch)
您正在手工制作 SQL 语句,这很好,但是您没有利用 pgx
来帮助解决这个问题(见下文)。
像这样附加到 SQL 字符串对于大输入可能效率低下
dollars = fmt.Sprintf("%s($%d, $%d),", dollars, count, count+1)
但最终值也有一个尾随 ,
,而您需要一个终止字符 ;
来指示语句的结尾。
顺便说一句,这个字符串截断行是多余的:
sqlStr = sqlStr[0 : len(sqlStr)-1] // this is a NOOP
无论如何,在制作长字符串时最好使用 strings.Builder 等性能更高的东西。
从 pgx
文档中,使用 pgx.Conn.CopyFrom:
func (c *Conn) CopyFrom(tableName Identifier, columnNames []string, rowSrc CopyFromSource) (int, error)
CopyFrom uses the PostgreSQL copy protocol to perform bulk data insertion. It returns the number of rows copied and an error.
example usage 副本:
rows := [][]interface{}{
{"John", "Smith", int32(36)},
{"Jane", "Doe", int32(29)},
}
copyCount, err := conn.CopyFrom(
pgx.Identifier{"people"},
[]string{"first_name", "last_name", "age"},
pgx.CopyFromRows(rows),
)