【问题标题】:how to batch insert and get results by sqlx in postgres如何在postgres中通过sqlx批量插入和获取结果
【发布时间】:2021-08-21 05:21:30
【问题描述】:

插入一条记录很容易得到这样的结果:

    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, question_id, type, choices, content) VALUES ($1, $2, $3, $4, $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, d.QuizAnswerID, d.QuestionID, d.Type, 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

提前致谢

【问题讨论】:

    标签: postgresql go sqlx pq


    【解决方案1】:

    我无法专门为您提供 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()
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-10-07
      • 1970-01-01
      • 2016-04-03
      • 2014-08-21
      相关资源
      最近更新 更多