Golang中使用sqlx实现INSERT INTO并获取返回值的方法

Golang中使用sqlx实现INSERT INTO并获取返回值的方法 我正在尝试使用AJAX调用一个Go API,该API将数据插入Postgresql。

  1. 这是在Postgresql中执行的查询。该查询可以正常工作 DB Fiddle - SQL Database Playground

  2. 这是将查询插入Postgresql的API(使用sqlx):

func endpoint { //simplified
    data = new(query, val)
    json.NewEncoder(w).Encode(data)

func new(query string, val string) interface{} {
    data := db.MustExec(query, val)
    return data
}
  1. 这是发送REST请求以获取所有响应头的AJAX代码: Edit fiddle - JSFiddle - Code Playground 或者,这是针对响应头中返回 {"Locker":{}} 的正确代码: Edit fiddle - JSFiddle - Code Playground 期望的结果应该是 {"tsk_id": "33"}(新插入的ID号)

我的目标是从 INSERT INTO 语句中获取新添加的 tsk_id。 看起来 MustExec 返回的响应头没有被正确更新或转换。 欢迎提供任何线索!


更多关于Golang中使用sqlx实现INSERT INTO并获取返回值的方法的实战教程也可以访问 https://www.itying.com/category-94-b0.html

3 回复

我不熟悉 sqlx,但在普通的 database/sql 中,你可以使用 db.Querydb.QueryRow 来执行插入操作,然后查询中的 RETURNING tsk_id 部分会作为该行的一个标量值返回。

func main() {
    fmt.Println("hello world")
}

更多关于Golang中使用sqlx实现INSERT INTO并获取返回值的方法的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


db.QueryRow 用于执行

感谢为我指明了正确的方向。这个方法似乎可行。

func Create(w http.ResponseWriter, r *http.Request) { // 简化版
	data = new(query, val)
	json.NewEncoder(w).Encode(data)
}

// 添加新记录
func new(query string, val string) interface{} {
	var id int
	err := db.QueryRowx(query, val).Scan(&id)
	if err != nil {
		return nil
	}
	return (id)
}

编辑代码片段 - JSFiddle - 代码游乐场 现在期望的结果是 {"120"}(新插入的编号)

在Golang中使用sqlx获取INSERT操作的返回值,需要使用RETURNING子句配合查询方法。以下是几种实现方式:

方法1:使用QueryRow/QueryRowx(推荐)

package main

import (
    "database/sql"
    "encoding/json"
    "fmt"
    "log"
    "net/http"
    
    _ "github.com/lib/pq"
    "github.com/jmoiron/sqlx"
)

type Task struct {
    TskID int `db:"tsk_id" json:"tsk_id"`
}

func insertTask(db *sqlx.DB, query string, val string) (Task, error) {
    var task Task
    // 使用QueryRowx并Scan到结构体
    err := db.QueryRowx(query, val).StructScan(&task)
    return task, err
}

func endpointHandler(w http.ResponseWriter, r *http.Request, db *sqlx.DB) {
    query := `
        INSERT INTO tsk (tsk_title) 
        VALUES ($1) 
        RETURNING tsk_id
    `
    val := "New Task Title"
    
    task, err := insertTask(db, query, val)
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }
    
    w.Header().Set("Content-Type", "application/json")
    json.NewEncoder(w).Encode(task)
}

方法2:使用NamedExec和LastInsertId(需要适配PostgreSQL)

func insertTaskNamed(db *sqlx.DB) (Task, error) {
    query := `
        INSERT INTO tsk (tsk_title) 
        VALUES (:tsk_title) 
        RETURNING tsk_id
    `
    
    task := map[string]interface{}{
        "tsk_title": "New Task",
    }
    
    var result Task
    rows, err := db.NamedQuery(query, task)
    if err != nil {
        return result, err
    }
    defer rows.Close()
    
    if rows.Next() {
        err = rows.StructScan(&result)
    }
    return result, err
}

方法3:使用Exec并获取LastInsertId(注意:PostgreSQL需要特殊处理)

func insertTaskExec(db *sqlx.DB) (int64, error) {
    query := `
        INSERT INTO tsk (tsk_title) 
        VALUES ($1) 
        RETURNING tsk_id
    `
    
    var tskID int64
    // 使用QueryRow而不是Exec
    err := db.QueryRow(query, "New Task").Scan(&tskID)
    return tskID, err
}

完整API示例

package main

import (
    "encoding/json"
    "log"
    "net/http"
    
    "github.com/jmoiron/sqlx"
    _ "github.com/lib/pq"
)

var db *sqlx.DB

func initDB() {
    var err error
    db, err = sqlx.Open("postgres", "user=postgres dbname=test sslmode=disable")
    if err != nil {
        log.Fatal(err)
    }
}

func insertHandler(w http.ResponseWriter, r *http.Request) {
    if r.Method != http.MethodPost {
        http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
        return
    }
    
    // 解析请求体
    var request struct {
        Title string `json:"title"`
    }
    
    if err := json.NewDecoder(r.Body).Decode(&request); err != nil {
        http.Error(w, "Invalid request body", http.StatusBadRequest)
        return
    }
    
    // 执行插入并获取返回值
    query := `
        INSERT INTO tsk (tsk_title) 
        VALUES ($1) 
        RETURNING tsk_id
    `
    
    var response struct {
        TskID int `json:"tsk_id"`
    }
    
    err := db.QueryRow(query, request.Title).Scan(&response.TskID)
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }
    
    w.Header().Set("Content-Type", "application/json")
    json.NewEncoder(w).Encode(response)
}

func main() {
    initDB()
    defer db.Close()
    
    http.HandleFunc("/insert", insertHandler)
    log.Fatal(http.ListenAndServe(":8080", nil))
}

关键点说明

  1. 必须使用RETURNING子句:PostgreSQL的INSERT语句需要RETURNING来返回插入的值
  2. 使用QueryRow而不是MustExecMustExec不返回结果集,只返回sql.Result
  3. 直接Scan到变量:使用QueryRow().Scan()获取单个返回值
  4. JSON响应:确保正确设置Content-Type为application/json

你的SQL查询应该像这样:

INSERT INTO tsk (tsk_title) 
VALUES ($1) 
RETURNING tsk_id

这样API将返回正确的JSON格式:{"tsk_id": 33}

回到顶部