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

时间:2017-08-14 17:06:31

标签: postgresql go

交易中插入行

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

是的,我正在使用Postgres。

我在这里缺少什么? THX!

/**
 * 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

目前这是一个有效的解决方案,欢迎进一步改进。

/**
 * 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

1 个答案:

答案 0 :(得分:2)

这是因为您用于go的postgresql驱动程序不支持LastInsertedId()功能。您没有说出您使用的是哪个驱动程序,但我已将此问题与github.com/lib/pq一起使用。

答案是在原始示例中使用QueryRow 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