Oracle 中获取最后插入记录 ID 的完整 Go 实战指南
一款功能相当强大的录音及音频编辑软件,不仅可以编辑音频,而且还可以录音,功能丰富,操作简单,使用方便,实用性强,并且占用电脑内存小,运行速度快,不卡顿电脑,使电脑系统保持良好的运行状态。支持许多格式的音频文件,包括WAV、OGG、VOC、IFF、AIFF、
在Go操作Oracle时,强烈推荐使用INSERT...RETURNING...INTO子句配合sqlx.QueryRow()获取自动生成的主键。该方法保证原子性和安全性,能够有效避免LastInsertId()在Oracle中不可用及SELECTMAX(id)造成的并发竞争问题,是主从表级联插入场景中获取主键的业界公认最佳实践。
正确的姿势:RETURNING ... INTO + sqlx.QueryRow
先假设你有这样一张表,主键通过序列和触发器自动生成:CREATE TABLE t (
x INT PRIMARY KEY,
created_at DATE DEFAULT SYSDATE
);
CREATE SEQUENCE x_seq START WITH 1 INCREMENT BY 1;
CREATE OR REPLACE TRIGGER t_bi_trg
BEFORE INSERT ON t FOR EACH ROW
BEGIN
SELECT x_seq.NEXTVAL INTO :NEW.x FROM DUAL;
END;
在 Go 代码里,千万别再尝试 `r.LastInsertId()` 了。正确的做法是用 `sqlx.QueryRow()` 执行带 `RETURNING` 的插入语句:
package main
import (
"fmt"
"log"
"github.com/jmoiron/sqlx"
_ "github.com/mattn/go-oci8"
)
func main() {
db, err := sqlx.Connect("oci8", "user/pass@localhost:49161/xe")
if err != nil {
log.Fatal("连接失败:", err)
}
defer db.Close()
// 关键点:用 RETURNING 子句把刚插入的主键拿回来
var insertedID int
err = db.QueryRow(
"INSERT INTO t (created_at) VALUES (SYSDATE) RETURNING x INTO ?",
&insertedID,
).Err()
if err != nil {
log.Fatal("插入并获取 ID 失败:", err)
}
fmt.Printf("成功插入,生成主键 ID: %d\n", insertedID)
// 现在可以安全地用于第二条插入(外键关联)
_, err = db.Exec(
"INSERT INTO related_table (t_id, remark) VALUES (?, 'from Go')",
insertedID,
)
if err != nil {
log.Fatal("插入从表失败:", err)
}
}
需要留意几个关键点:
- `RETURNING ... INTO ?` 是 Oracle 原生的命令,go-oci8 驱动通过 `QueryRow` 加地址参数就能直接接收返回值;
- 必须使用 `QueryRow()`、`Get()` 或 `Select()`,不能用 `Exec()`——因为 `Exec()` 不支持返回值绑定;
- 虽然 sqlx 对命名参数也有支持,但 go-oci8 对命名参数的支持不太稳定,建议优先用位置占位符 `?`;
- 注意,`RETURNING` 是在同一个事务内原子执行的,不需要额外加锁,天生就保证了事务安全和并发安全;
- 无论你的主键是来自序列、UUID 函数还是 `SYS_GUID()`,只要 `RETURNING` 指定的是你的目标列,都能可靠拿回。
常见误区,挨个澄清一下
现在回过头看看,有几个坑是初学者最容易踩的:- LastInsertId() 就不要想了:Oracle 的 Go 驱动(不管是 go-oci8 还是 goracle)都没有实现这个接口,调用就是报错;
- 千万别用 SELECT MAX(id) 来凑:高并发下读到别的会话插入的 ID 是很常见的事,还得加锁,性能也差;
- 存储函数里包 DML 再 SELECT 也不行:Oracle 禁止在 SELECT 中执行 DML,违反读一致性原则,会直接报 ORA-14551;
- PL/SQL 块加输出变量倒是可行:用 `sqlx.QueryRow().Scan()` 或 `database/sql` 的 `Out` 参数都能搞定,不过相比之下,`QueryRow(...).Scan(&id)` 是最简洁、最不容易出错的写法。
更进一步:封装成一个可复用的函数
如果这个操作在你的项目里出现的频率比较高,完全可以把它封装起来:func InsertAndGetID(db *sqlx.DB, table, pkCol string, cols []string, values ...interface{}) (int, error) {
placeholders := make([]string, len(cols))
for i := range cols {
placeholders[i] = "?"
}
query := fmt.Sprintf(
"INSERT INTO %s (%s) VALUES (%s) RETURNING %s INTO ?",
table,
strings.Join(cols, ", "),
strings.Join(placeholders, ", "),
pkCol,
)
var id int
err := db.QueryRow(query, append(values, &id)...).Err()
return id, err
}
总的来说,在 Go 与 Oracle 配合的场景下,`INSERT ... RETURNING ... INTO ?` 就是获取新插入主键的标准答案。它既高效又安全,完美适配主-从表的级联插入需求,不需要额外查询,没有并发风险。可以说,这是每一位用 Go 操作 Oracle 的开发者都应该熟练掌握的基本功。
Shapr3D是一款面向工业设计、机械工程、建筑概念和三维打印工作流的CAD软件。Mac版采用Parasolid建模内核,支持草图约束、实体建模、工程图、可视化渲染及常见CAD格式交换,并可通过账户在多台设备之间同步项目。
REAPER是Cockos开发的数字音频工作站,提供多轨音频与MIDI录制、剪辑、处理、混音和母带制作工具。Mac版兼容Intel与Apple芯片,支持AU、VST、VST3、CLAP等插件格式,并提供高度可定制的工作流程。
Ableton Live 是面向音乐制作人与现场表演者的数字音频工作站,提供编曲视图、独具特色的现场视图、音频录制、MIDI创作、实时变速、乐器及效果器。Mac版原生支持Apple芯片,并可连接音频接口、MIDI控制器和第三方插件。
Photoshop 2026 是 Adobe 推出的专业图像处理与视觉设计软件,支持 Windows、macOS 和 iPad 等平台,广泛应用于摄影修图、电商设计、平面海报、数字绘画及视觉合成等创作场景。
Blender 是一款免费开源、跨平台的专业 3D 创作软件,集建模、动画、渲染、视频编辑与视觉合成等功能于一体,广泛应用于影视动画、游戏设计和建筑可视化等领域。软件支持 Cycles 物理渲染器与 Eevee 实时渲染引擎,并提供多边形建模、骨骼绑定、物理模拟等专业工具。Blender 兼容 Windows、macOS 和 Linux 系统,安装包轻巧、运行流畅,依托活跃的全球开发者社区持续更新,是从初学者到专业创作者都值得选择的正版 3D 创作工具。














