Go:如何在sqlx中使用LastInsertId()与Postgres的关系

501 阅读1分钟

在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