Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/svg/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Postgresql 需要在事务中插入当前行的ID_Postgresql_Go - Fatal编程技术网

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

Postgresql 需要在事务中插入当前行的ID,postgresql,go,Postgresql,Go,在事务中我正在插入一行 如何访问并返回插入行的ID。 正如您在下面的代码中所看到的(请参见注释//返回上次插入的ID.),我尝试使用LastInsertedId()函数,但它返回了一个错误 顺便说一句,我用的是Postgres 我错过了什么? 谢谢 这是一个目前有效的解决方案,欢迎进一步改进 /** * Creates order and returns its ID. */ func createOrder(w http.ResponseWriter, r *http.Request) (

事务中我正在插入一行

如何访问并返回插入行的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.
    _, 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