发布于2026-07-10 阅读(0)
扫一扫,手机访问
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)
}
}
需要留意几个关键点:
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 的开发者都应该熟练掌握的基本功。
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
正版软件
正版软件
正版软件
正版软件
正版软件
1
2
3
7
8