如何在postgres中使用sqlx获取最后插入行的uuid

How to get uuid of last inserted row using sqlx in postgres

我像这样使用 SQLx table 在 table 中插入一些数据

func (*RideRepositoryImpl) insert(entity interface{}, tx persistence.Transaction) (sql.Result, error) {
    ride := entity.(*model.Ride)

    placeHolders := repository.InsertPlaceholders(len(rideColumns))
    sql := fmt.Sprintf("INSERT INTO %s(%s) VALUES(%s)", TableName, strings.Join(Columns, ","), placeHolders)
    return tx.Exec(sql, ride.ID.String(), ride.DeviceIotID, ride.VehicleID.String(), ride.UserID.String(),ride.AdditionComments)
}

并像这样调用这个函数

func (p *RideRepositoryImpl) Save(ride *model.Ride, tx persistence.Transaction) error {
    return repository.Save(ride, p.insert, tx)

现在我想在保存这条记录后立即获取保存记录的UUID。有什么干净的方法可以立即做到这一点吗?

PostgreSQL 对此有 RETURNING 子句。

Sometimes it is useful to obtain data from modified rows while they are being manipulated. The INSERT, UPDATE, and DELETE commands all have an optional RETURNING clause that supports this. Use of RETURNING avoids performing an extra database query to collect the data, and is especially valuable when it would otherwise be difficult to identify the modified rows reliably.

// add the RETURNING clause to your INSERT query
sql := fmt.Sprintf("INSERT INTO %s(%s) VALUES(%s) RETURNING <name_of_uuid_column>", TableName, strings.Join(Columns, ","), placeHolders)

// use QueryRow instead of Exec
row := tx.QueryRow(sql, ride.ID.String(), ride.DeviceIotID, ride.VehicleID.String(), ride.UserID.String(),ride.AdditionComments)

// scan the result of the query
var uuid string
if err := row.Scan(&uuid); err != nil {
    panic(err)
}

// ...

有关 RETURNING 的其他 INSERT 特定信息,您可以转到 INSERT 文档并使用 CTRL/CMD+F 在页面中搜索“returning” .


此外,如果您需要您的函数仍然 return 一个 sql.Result 值来满足某些要求,那么您可以 return 您自己的实现。

var _ sql.Result = sqlresult{} // compiler check

type sqlresult struct { lastid, nrows int64 }

func (r sqlresult) LastInsertId() (int64, error) { return r.lastid, nil }
func (r sqlresult) RowsAffected() (int64, error) { return r.nrows, nil }

func (*RideRepositoryImpl) insert(entity interface{}, tx persistence.Transaction) (sql.Result, error) {
    ride := entity.(*model.Ride)

    placeHolders := repository.InsertPlaceholders(len(rideColumns))
    sql := fmt.Sprintf("INSERT INTO %s(%s) VALUES(%s) RETURNING <name_of_uuid_column>", TableName, strings.Join(Columns, ","), placeHolders)
    row := tx.QueryRow(sql, ride.ID.String(), ride.DeviceIotID, ride.VehicleID.String(), ride.UserID.String(),ride.AdditionComments)
    if err := row.Scan(&ride.<NameOfUUIDField>); err != nil {
        return nil, err
    }
    return sqlresult{0, 1}, nil
}