Postgresql 需要在事务中插入当前行的ID
在事务中我正在插入一行 如何访问并返回插入行的ID。 正如您在下面的代码中所看到的(请参见注释//返回上次插入的ID.),我尝试使用LastInsertedId()函数,但它返回了一个错误 顺便说一句,我用的是Postgres 我错过了什么? 谢谢 这是一个目前有效的解决方案,欢迎进一步改进Postgresql 需要在事务中插入当前行的ID,postgresql,go,Postgresql,Go,在事务中我正在插入一行 如何访问并返回插入行的ID。 正如您在下面的代码中所看到的(请参见注释//返回上次插入的ID.),我尝试使用LastInsertedId()函数,但它返回了一个错误 顺便说一句,我用的是Postgres 我错过了什么? 谢谢 这是一个目前有效的解决方案,欢迎进一步改进 /** * Creates order and returns its ID. */ func createOrder(w http.ResponseWriter, r *http.Request) (
/**
* 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
发生这种情况是因为您用于go的postgresql驱动程序不支持
LastInsertedId()
函数。您没有说您使用的是哪个驱动程序,但我在使用github.com/lib/pq
时遇到了这个问题
答案是使用QueryRow
而不是原始示例中的Exec
。只需确保您在查询中使用了返回ID的,并将其视为select
下面是一个例子(我没有测试这个,我可能遗漏了一些东西,但你知道了):
改为尝试stmt.QueryRow(order.CustomerID),然后从行中获取id。请参阅,您可以使用id作为序列号,然后直接使用max(id)从代码中调用查询,这将给出最后插入的行。在postgres中,序列号与序列号相同。@saarrrr:thx这很有帮助!我将根据您的提示使用有效的解决方案更新我的问题。这不安全。如果另一个查询插入并提交,您将获得其id,而不是您的id。
/**
* 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
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