You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用goracle包向Oracle的A_LOB_TABLE插入BLOB图片报错ORA-22922

解决goracle插入BLOB时ORA-22922错误的方案

你遇到的ORA-22922: nonexistent LOB value错误,核心原因是临时LOB的生命周期和事务不匹配,咱们一步步拆解问题,再给你两个可行的解决办法:

问题根源

  • 你在事务tx里创建了临时LOB,但插入操作却用了testDb.Exec——这相当于开启了一个全新的独立事务,原来事务里的LOB定位器在这个新事务里已经失效了。
  • 而且你还defer tx.Rollback(),就算你改用tx.Exec插入,最后回滚事务也会把临时LOB直接销毁,导致插入失败。

方案一:直接插入字节数组(推荐,更简洁)

goracle其实支持直接将字节数组作为BLOB参数传入,不需要手动创建临时LOB,代码会简化很多:

ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()

// 读取图片文件
dat, err := ioutil.ReadFile("./sample.png")
if err != nil {
    fmt.Println(".....Error Opening File")
    fmt.Println(err)
    return
}

// 开启事务执行插入(也可根据需求去掉事务)
tx, err := testDb.BeginTx(ctx, nil)
if err != nil {
    fmt.Println(err)
    return
}
defer func() {
    if r := recover(); r != nil {
        tx.Rollback()
    }
}()

_, err = tx.ExecContext(ctx, "insert into A_LOB_TABLE(id, image) VALUES(:1, :2)", 1, dat)
if err != nil {
    fmt.Println(".....Error Inserting data - BLOB")
    fmt.Println(err)
    tx.Rollback()
    return
}

// 提交事务保存数据
if err := tx.Commit(); err != nil {
    fmt.Println("Failed to commit transaction:", err)
    tx.Rollback()
    return
}

fmt.Println("Image inserted successfully!")

方案二:修正临时LOB的事务逻辑

如果你一定要用临时LOB的方式,需要保证所有操作(创建LOB、写入数据、插入表)都在同一个事务里,并且最后提交事务而不是回滚:

ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()

tx, err := testDb.BeginTx(ctx, nil)
if err != nil {
    fmt.Println(err)
    return
}
defer func() {
    if r := recover(); r != nil {
        tx.Rollback()
    }
}()

// 创建临时LOB(会话级)
qry := `DECLARE tmp BLOB; BEGIN DBMS_LOB.createtemporary(tmp, TRUE, DBMS_LOB.SESSION); :1 := tmp; END;`
stmt, err := tx.PrepareContext(ctx, qry)
if err != nil {
    fmt.Printf("%s: %w", qry, err)
    tx.Rollback()
    return
}
defer stmt.Close()

var tmp goracle.Lob
if _, err := stmt.ExecContext(ctx, goracle.LobAsReader(), sql.Out{Dest: &tmp}); err != nil {
    fmt.Printf("Failed to create temporary lob: %+v", err)
    tx.Rollback()
    return
}

// 读取图片文件
dat, err := ioutil.ReadFile("./sample.png")
if err != nil {
    fmt.Println(".....Error Opening File")
    fmt.Println(err)
    tx.Rollback()
    return
}

// 写入数据到临时LOB
if _, err := tx.ExecContext(ctx, "BEGIN dbms_lob.append(:1, :2); END;", tmp, goracle.Lob{Reader: bytes.NewReader(dat)}); err != nil {
    fmt.Printf("Failed to write buffer to lob: %+v", err)
    tx.Rollback()
    return
}

// 在同一个事务里执行插入
_, err = tx.ExecContext(ctx, "insert into A_LOB_TABLE(id, image) VALUES(:1, :2)", 1, tmp)
if err != nil {
    fmt.Println(".....Error Inserting data - BLOB")
    fmt.Println(err)
    tx.Rollback()
    return
}

// 提交事务,保存数据和LOB
if err := tx.Commit(); err != nil {
    fmt.Println("Failed to commit transaction:", err)
    tx.Rollback()
    return
}

fmt.Println("Image inserted successfully using temporary LOB!")

内容的提问来源于stack exchange,提问作者Lucas

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 08:27:30