如何在postgres中通过sqlx批量插入并获取结果

问题描述

插入一条记录并得到如下结果很容易:

    s := "INSERT INTO quiz_answer_details (quiz_answer_id,question_id,type,choices,content) VALUES ($1,$2,$3,$4,$5) RETURNING *"
    d,err := fromQuizAnswerDetail(in)
    if err != nil {
        return nil,err
    }
    var out quizAnswerDetail
    if err := m.core.GetContextOnMaster(ctx,&out,s,d.QuizAnswerID,d.QuestionID,d.Type,d.Choices,d.Content); err != nil {
        return nil,err
    }

但是如何进行批量插入并获得所有结果?我尝试了几种方法,但一无所获。

这是我认为应该工作但它没有

    s := "INSERT INTO quiz_answer_details (quiz_answer_id,$5) RETURNING *"
    data,err := fromQuizAnswerDetails(ins)
    if err != nil {
        return nil,err
    }
    dbs,_ := m.core.GetAllMasters()
    stmt,err := dbs[0].PreparexContext(ctx,s)
    if err != nil {
        return nil,err
    }
    var out quizAnswerDetails
    for _,d := range data {
        var detail quizAnswerDetail
        if err := stmt.GetContext(ctx,&detail,pq.Array(d.Choices),d.Content); err != nil {
            return nil,err
        }
        out = append(out,detail)
    }
    return out.to()

错误信息是这样的:

 quiz-answer_test.go:35: driver: skip fast-path; continue as if unimplemented

提前致谢

解决方法

我无法专门为您提供 sqlx 的帮助,因为我不熟悉该包,但是在使用标准库的 database/sql 包时,可以执行如下所示的批量插入。

如果需要编写的不同批处理查询的数量很多,或者如果项目处于设计阶段并且数据库架构的更改比人们希望的更频繁,则它非常冗长并且可能变得难以维护。在这些情况下,下面的示例可以使用反射进行泛化,或者像我喜欢的那样,可以编写一个生成器来为您编写代码。

var queryString = `INSERT INTO "quiz_answer_details" (
    "quiz_answer_id","question_id","type","choices","content"
) VALUES ` // `

// 5 = the number of columns you want to insert per row
params := make([]interface{},len(ins)*5)
for i,v := range ins {
    pos := i * 5

    // aggregate all fields into a single slice
    params[pos+0] = v.QuizAnswerID
    params[pos+1] = v.QuestionID
    params[pos+2] = v.Type
    params[pos+3] = pq.Array(v.Choices)
    params[pos+4] = v.Content

    // construct the ($N,$N,...) lists for the VALUES clause
    queryString += `($` + strconv.Itoa(pos+0) +
        `,$` + strconv.Itoa(pos+1) +
        `,$` + strconv.Itoa(pos+2) +
        `,$` + strconv.Itoa(pos+3) +
        `,$` + strconv.Itoa(pos+4) +
        `),`
}

queryString = queryString[:len(queryString)-1] // drop the last comma
queryString += ` RETURNING *`

rows,err := db.QueryContext(ctx,queryString,params...)
if err != nil {
    return err
}
defer rows.Close()

i := 0
for rows.Next() {
    err := rows.Scan(
        // NOTE: since you're using "RETURNING *" you need to
        // provide fields for every column that will be returned,// and you need to make sure that the fields are in the
        // same order in which their corresponding columns are
        // declared in the table.
        //
        // NOTE: postgres,AFAIK,does NOT GUARANTEE that the returned
        // rows will be in the same order in which they were inserted,// therefore the contents of the input slice may be in a
        // different order after scanning is done.
        &ins[i].QuizAnswerID,&ins[i].QuestionID,&ins[i].Type,pq.Array(&ins[i].Choices),&ins[i].Content,)
    if err != nil {
        return err
    }

    i += 1
}
return rows.Err()

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...