需要在事务中插入当前行的 ID

old*_*ort 5 postgresql go

在一个事务中,插入了一行

如何访问和返回插入行的 ID。正如您在下面的代码中看到的(参见注释下的 // 返回最后插入的 ID。)我尝试使用LastInsertedId()函数,但它给了我一个错误。

顺便说一句,我正在使用 Postgres。

我在这里缺少什么?谢谢!

/**
 * Creates order and returns its ID.
 */
func createOrder(w http.ResponseWriter, r *http.Request) (orderID int) {

    // Begin.
    tx, err := db.Begin()
    if err != nil {
        log.Fatal(err)
    }

    // Db query.
    sqlQuery := `INSERT INTO ORDER_CUSTOMER
        (CUSTOMER_ID)
        VALUES ($1)
        RETURNING ID`

    // Prepare.
    stmt, err := tx.Prepare(sqlQuery)
    if err != nil {
        log.Fatal(err)
        return
    }

    // Defer Close.
    defer stmt.Close()

    customerEmail := validateSession(r)
    ID := getIDFromCustomer(customerEmail)
    order := order{}
    order.CustomerID = ID

    // Exec.
    ret, err := stmt.Exec(order.CustomerID)

    // Rollback.
    if err != nil {
        tx.Rollback()
        e := errors.New(err.Error())
        msg.Warning = e.Error()
        tpl.ExecuteTemplate(w, "menu.gohtml", msg)
        return
    }

    // Return last Inserted ID.
    lastID, err := ret.LastInsertId()
    if err != nil {
        orderID = 0
    } else {
        orderID = int(lastID)
    }

    // Commit.
    tx.Commit()

    return orderID
} // createOrder
Run Code Online (Sandbox Code Playgroud)

这是目前的工作解决方案,欢迎进一步改进。

/**
 * Creates order and returns its ID.
 */
func createOrder(w http.ResponseWriter, r *http.Request) (orderID int) {

    // Begin.
    tx, err := db.Begin()
    if err != nil {
        log.Fatal(err)
    }

    // Db query.
    sqlQuery := `INSERT INTO ORDER_CUSTOMER
        (CUSTOMER_ID)
        VALUES ($1)
        RETURNING ID`

    // Prepare.
    stmt, err := tx.Prepare(sqlQuery)
    if err != nil {
        log.Fatal(err)
        return
    }

    // Defer Close.
    defer stmt.Close()

    customerEmail := validateSession(r)
    ID := getIDFromCustomer(customerEmail)
    order := order{}
    order.CustomerID = ID

    // Exec.
    _, err = stmt.Exec(order.CustomerID)

    // Rollback.
    if err != nil {
        tx.Rollback()
        e := errors.New(err.Error())
        msg.Warning = e.Error()
        tpl.ExecuteTemplate(w, "menu.gohtml", msg)
        return
    }

    // Return last Inserted ID.
    //lastID, err := ret.LastInsertId()
    err = stmt.QueryRow(order.CustomerID).Scan(&orderID)
    if err != nil {
        orderID = 0
    }

    // Commit.
    tx.Commit()

    return orderID
} // createOrder
Run Code Online (Sandbox Code Playgroud)

Top*_*opo 5

发生这种情况是因为您用于 go 的 postgresql 驱动程序不支持该LastInsertedId()功能。您没有说明您使用的是哪个驱动程序,但我在使用github.com/lib/pq.

对此的答案是在原始示例中使用QueryRowinsted Exec。只需确保您RETURNING ID在查询中使用并将其视为选择。

这是一个例子(我没有测试这个,我可能会遗漏一些东西,但你明白了):

func createOrder(w http.ResponseWriter, r *http.Request) (orderID int) {

    // Begin.
    tx, err := db.Begin()
    if err != nil {
        log.Fatal(err)
    }

    // Db query.
    sqlQuery := `INSERT INTO ORDER_CUSTOMER
        (CUSTOMER_ID)
        VALUES ($1)
        RETURNING ID`

    // Prepare.
    stmt, err := tx.Prepare(sqlQuery)
    if err != nil {
        log.Fatal(err)
        return
    }

    // Defer Close.
    defer stmt.Close()

    customerEmail := validateSession(r)
    ID := getIDFromCustomer(customerEmail)
    order := order{}
    order.CustomerID = ID

    // Exec.
    var orderID int // Or whatever type you are using
    err := stmt.QueryRow(order.CustomerID).Scan(&orderID)

    // Rollback.
    if err != nil {
        //if something goes wrong set the orderID to 0 as in your original code
        orderID = 0
        tx.Rollback()
        e := errors.New(err.Error())
        msg.Warning = e.Error()
        tpl.ExecuteTemplate(w, "menu.gohtml", msg)
        return
    }

    // Commit.
    tx.Commit()

    return orderID
} // createOrder
Run Code Online (Sandbox Code Playgroud)