go data_error ai_generated true

sql: Rows are closed, cannot call LastInsertId on result

ID: go/sql-rows-err-lastinsertid

Also available as: JSON · Markdown · 中文
80%Fix Rate
85%Confidence
1Evidence
2024-01-10First Seen

Version Compatibility

VersionStatusIntroducedDeprecatedNotes
Go 1.15 active — — —
Go 1.16 active — — —
Go 1.17 active — — —
Go 1.18 active — — —
Go 1.19 active — — —
Go 1.20 active — — —
Go 1.21 active — — —
Go 1.22 active — — —
Go 1.23 active — — —

Root Cause

Calling Result.LastInsertId() on a sql.Result from an INSERT that used a SELECT or RETURNING clause, or after rows have been consumed.

generic

中文

对来自使用 SELECT 或 RETURNING 子句的 INSERT 的 sql.Result 调用 Result.LastInsertId(),或在行已被消耗后调用。

Official Documentation

https://pkg.go.dev/database/sql#Result.LastInsertId

Workarounds

  1. 90% success Use db.Exec() for INSERT statements without RETURNING; use db.QueryRow() with RETURNING and scan into a variable
    Use db.Exec() for INSERT statements without RETURNING; use db.QueryRow() with RETURNING and scan into a variable
  2. 85% success Access LastInsertId immediately after Exec() before any rows iteration
    Access LastInsertId immediately after Exec() before any rows iteration
  3. 80% success For PostgreSQL with RETURNING, use a separate SELECT currval() or lastval() query
    For PostgreSQL with RETURNING, use a separate SELECT currval() or lastval() query

中文步骤

  1. Use db.Exec() for INSERT statements without RETURNING; use db.QueryRow() with RETURNING and scan into a variable
  2. Access LastInsertId immediately after Exec() before any rows iteration
  3. For PostgreSQL with RETURNING, use a separate SELECT currval() or lastval() query

Dead Ends

Common approaches that don't work:

  1. 90% fail

    Rows.Close() closes the result set, making LastInsertId unavailable; order is wrong.

  2. 60% fail

    db.Exec() returns a Result that supports LastInsertId, but if the INSERT has a RETURNING clause, it still fails.

  3. 95% fail

    The result is tied to the original query; reconnecting doesn't recover the last insert ID.