Golang操作PostgreSQL插入数据后如何获取返回的行记录及自增ID
解决方案
PostgreSQL 原生支持在 INSERT 语句末尾追加 RETURNING 子句,可以在插入的同时直接返回指定列甚至整行数据,完全不需要二次查询,也不需要依赖驱动的LastInsertId方法。
你遇到的
LastInsertId is not supported by this driver报错属于正常情况,PostgreSQL主流Go驱动(pq、pgx)均未实现该方法,优先使用RETURNING语法即可,该方式不存在并发场景下拿错ID的问题,灵活性和安全性更高。
代码改造示例
1. 仅返回自增ID
如果只需要获取自增ID(假设ID列名为id),修改查询语句追加RETURNING id,用db.QueryRow替代db.Exec执行即可:
var cols = "(col1, col2, col3)" var values = "($1, $2, $3)" // 末尾追加RETURNING子句指定返回自增ID var query = fmt.Sprintf("INSERT INTO %s %s VALUES %s RETURNING id", myTable, cols, values) var insertId int64 // 执行查询并扫描返回的ID err := db.QueryRow(query, thing.val1, thing.val2, thing.val3).Scan(&insertId) if err != nil { // 错误处理逻辑 } // insertId 即为刚插入数据的自增ID
2. 返回完整插入行
如果需要拿到插入的所有字段数据,直接将RETURNING后的参数改为*,按返回字段顺序扫描到对应变量即可:
var cols = "(col1, col2, col3)" var values = "($1, $2, $3)" var query = fmt.Sprintf("INSERT INTO %s %s VALUES %s RETURNING *", myTable, cols, values) // 定义结构体接收返回数据 type YourData struct { Id int64 Col1 string Col2 int Col3 bool } var insertedData YourData err := db.QueryRow(query, thing.val1, thing.val2, thing.val3).Scan( &insertedData.Id, &insertedData.Col1, &insertedData.Col2, &insertedData.Col3, // 其余字段按返回顺序依次填写 ) if err != nil { // 错误处理逻辑 }
补充说明
- 批量插入多条数据时,把
QueryRow替换为Query,循环遍历返回的结果集即可拿到所有插入行的数据。 - 不要直接拼接用户输入的表名、列名到SQL语句中,避免SQL注入风险,如果表名列名是动态生成的,一定要做好白名单校验。
内容的提问来源于stack exchange,提问作者alex
相关产品推荐
相关产品推荐

