在Go中使用sqlx
包和Postgres数据库时,你可能会遇到以下错误。
lastinsertid is not supported by this driver postgres
当你想访问一个新插入的实体的LastInsertId()
,这个错误会发生。在这篇文章中,我将告诉你如何在不对数据库做任何修改的情况下解决这个错误。
让我们来调查一下会发生这个错误的具体场景。
func CreateAppointment(appointment Appointment) int {
result, err := database.Db.NamedExec("INSERT INTO appointments (firstName, lastName, appointmentDateTime) VALUES (:firstName, :lastName, :appointmentDateTime)", appointment)
if err != nil {
log.Fatalln(err)
}
id, err := result.LastInsertId()
if err != nil {
log.Fatalln(err)
}
return id
}
CreateAppointment
函数试图将一个新条目持久化到Postgres数据库中。然后,它返回新持久化对象的id
。
但是上面的代码不起作用;sqlx
会抱怨Postgres不支持LastInsertId()
命令。
PrepareNamed来拯救
然而,这个问题有一个解决办法。
首先,我们需要修改INSERT INTO
语句。Postgres需要更明确地描述我们在插入完成后要返回什么。
INSERT INTO appointments (firstname, lastname,
appointmentdatetime) VALUES (:firstname, :lastname,
:appointmentdatetime) RETURNING id
通过添加RETURNING id
,我们告诉Postgres,条目的id
字段必须返回给客户端。
但是这个修正对NamedExec
函数不起作用。
基本上我们需要使用PrepareNamed
函数来代替。
func CreateAppointment(appointment Appointment) id {
stmt, err := database.Db.PrepareNamed("INSERT INTO appointments (firstname , lastname, appointmentdatetime) VALUES (:firstname, :lastname, :appointmentdatetime) RETURNING id")
var id int
err = stmt.Get(&id, appointment)
if err != nil {
log.Fatalln(err)
}
return id
}
有了这两个改动,现在可以正常返回id
。