2017-08-14 60 views
3

內插在一個交易當前行的ID我插入一行需要一個交易

我該如何才能訪問並返回插入行的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 
+4

嘗試stmt.QueryRow(order.CustomerID)代替,然後抓住號關該行。請參閱https://golang.org/pkg/database/sql/#Stmt.QueryRow – saarrrr

+0

您可以使用id作爲序列號,然後使用max(id)直接調用您的代碼中的查詢,這會爲您提供最後插入的行。 postgres,序列與序列相同。 – Ankur

+0

@saarrrr:thx幫助!我會根據您的提示更新我的問題,並提供一個可行的解決方案。 – oldsport

回答

1

這是因爲您正在使用去PostgreSQL的驅動程序不支持LastInsertedId()功能。你沒有說你正在使用哪個驅動程序,但我有這個問題與github.com/lib/pq

對此的回答是在原始示例中使用QueryRowExec insted。只要確保您在查詢中使用了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