【问题标题】:Bulk insert with sqlx使用 sqlx 批量插入
【发布时间】:2020-02-02 13:05:52
【问题描述】:

我正在尝试使用 sqlx 和 golang 进行批量插入:

    for _, result := range results {
            queryInsert := `INSERT INTO "DataCom_travel" (com1,com2,path,time) VALUES ($1,$2,$3,$4)`
            db.MustExec(queryInsert,result.Com1,result.Com2,result.Path,result.Time)
            queryUpdate := `UPDATE "DataCom_commcombinaison" set done = TRUE WHERE com1 =$1 and com2 =$2`
            db.MustExec(queryUpdate,result.Com1,result.Com2)
        }

该代码有效,但速度很慢。

我试过了:

tx := db.MustBegin()
for _, result := range results {
        queryInsert := `INSERT INTO "DataCom_travel" (com1,com2,path,time) VALUES ($1,$2,$3,$4)`
        tx.MustExec(queryInsert,result.Com1,result.Com2,result.Path,result.Time)
        queryUpdate := `UPDATE "DataCom_commcombinaison" set done = TRUE WHERE com1 =$1 and com2 =$2`
        tx.MustExec(queryUpdate,result.Com1,result.Com2)
    }
tx.Commit()

但是当我查看我的记录时它什么也没做,我没有看到任何记录。

问候

编辑:

INSERT INTO "DataCom_travel" (com1,com2,path,time) VALUES ($1,$2,$3,$4),($2,$3,$4,$5),($3,$4,$5,$6),($4,$5,$6,$7),($5,$6,$7,$8),($6,$7,$8,$9),($7,$8,$9,$10),($8,$9,$10,$11),($9,$10,$11,$12),($10,$11,$12,$13)
UPDATE "DataCom_commcombinaison" set done = TRUE WHERE (com1 = $1 AND com2 = $2 )  OR (com1 = $2 AND com2 = $3 )  OR (com1 = $3 AND com2 = $4 )  OR (com1 = $4 AND com2 = $5 )  OR (com1 = $5 AND com2 = $6 )  OR (com1 = $6 AND com2 = $7 )  OR (com1 = $7 AND com2 = $8 )  OR (com1 = $8 AND com2 = $9 )  OR (com1 = $9 AND com2 = $10 )  OR (com1 = $10 AND com2 = $11 ) 
panic: pq: column "com2" is of type integer but expression is of type text

【问题讨论】:

    标签: postgresql go sqlx


    【解决方案1】:

    您可以使用循环来构建单个插入并将参数聚合到一个切片中,然后只执行一次查询。像这样的:

    queryInsert := `INSERT INTO "DataCom_travel" (com1,com2,path,time) VALUES `
    queryUpdate := `UPDATE "DataCom_commcombinaison" set done = TRUE WHERE `
    
    insertparams := []interface{}{}
    updateparams := []interface{}{}
    
    for i, result := range results {
        p1 := i * 4 // starting position for insert params
        p2 := i * 2 // starting position for update params
    
        queryInsert += fmt.Sprintf("($%d,$%d,$%d,$%d),", p1+1,p1+2,p1+3,p1+4)
        queryUpdate += fmt.Sprintf("(com1=$%d AND com2=$%d) OR ", p2+1, p2+2)
    
        insertparams = append(insertparams, result.Com1, result.Com2, result.Path, result.Time)
        updateparams = append(updateparams, result.Com1, result.Com2)
    }
    
    queryInsert = queryInsert[:len(queryInsert)-1] // remove trailing ","
    queryUpdate = queryUpdate[:len(queryUpdate)-4] // remove trailing " OR "
    
    db.MustExec(queryInsert, insertparams...)
    db.MustExec(queryUpdate, updateparams...)
    

    【讨论】:

    • 我有一个我不明白的错误:pq:列“com2”是整数类型,但表达式是文本类型? int 中的每个数据如何变成文本? @mkopriva
    • @user462794 抱歉,我最初的答案版本对位置参数的计算有误,请参阅更新后的答案以获得正确的结果。
    【解决方案2】:

    使用另一个库生成查询,然后使用 sqlx 执行查询可能很有用。

    例如,使用squirrel:

    // Build query with Squirrel
    q := squirrel.Insert("DataCom_travel").Columns("com1", "com2", "path", "time")
    for _, result := range results  {
      q = q.Values(result.Com1, result.Com2, result.Path, result.Time)
    }
    sql, args, err := q.ToSql()
    if err != nil {
      return err
    }
    
    // Execure query with sqlx
    res, err := db.MustExec(sql, args...)
    

    【讨论】:

      【解决方案3】:

      您可以使用NamedExec 代替字符串连接。 sqlx README 底部有一个例子:https://github.com/jmoiron/sqlx/blob/master/README.md

      【讨论】:

        猜你喜欢
        • 2021-08-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-01-28
        • 2011-04-09
        • 2015-08-18
        • 2011-02-20
        相关资源
        最近更新 更多