为了账号安全,请及时绑定邮箱和手机立即绑定

如何将图像作为 BLOB 插入 Oracle 数据库

如何将图像作为 BLOB 插入 Oracle 数据库

Go
有只小跳蛙 2023-07-31 16:28:01
我有一个带有 A_LOB_TABLE 表的数据库:我想使用 goracle 包将具有任何(假设为“1”)ID 的 BLOB 图像插入到 A_LOB_TABLE 中。这是我的代码:ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)defer cancel()// To have a valid LOB locator, we have to keep the Stmt around.qry := `DECLARE tmp BLOB;BEGIN  DBMS_LOB.createtemporary(tmp, TRUE, DBMS_LOB.SESSION);  :1 := tmp;END;`    tx, err := testDb.BeginTx(ctx, nil)    if err != nil {        fmt.Println(err)    }    defer tx.Rollback()stmt, err := tx.PrepareContext(ctx, qry)if err != nil {    fmt.Printf("%s: %w", qry, err)}defer stmt.Close()var tmp goracle.Lobif _, err := stmt.ExecContext(ctx, goracle.LobAsReader(), sql.Out{Dest: &tmp}); err != nil {    fmt.Printf("Failed to create temporary lob: %+v", err)}fmt.Printf("tmp: %#v", tmp)// Get file as bytes (it needs to be in the same dir as code is)dat, err := ioutil.ReadFile("./sample.png")if err != nil {    fmt.Println(".....Error Opening File")    fmt.Println(err)    return}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(%v) to lob(%v): %+v", dat, tmp, err)}// INSERTING LOB - starting...._, err = testDb.Exec("insert into A_LOB_TABLE(id, image) VALUES(:1, :2)",  1, tmp)if err != nil {    fmt.Println(".....Error Inserting data - BLOB")    fmt.Println(err)    return}// INSERTING LOB - ended.但这不起作用。它在行输出错误_, err = testDb.Exec("insert into A_LOB_TABLE(id, image) VALUES(:1, :2)",  1, tmp)说:dpiStmt_execute(mode=32 arrLen=-1): ORA-22922: LOB 值不存在
查看完整描述

1 回答

?
慕尼黑的夜晚无繁华

TA贡献1864条经验 获得超6个赞

经过数十个小时尝试弄清楚如何使用 goracle Go 驱动程序将 BLOB 插入到 OracleDB 中,我得到了答案。


长话短说


完整代码(显然根据您的需要调整数据库连接和文件位置&&文件名等变量):


package main


import (

    "bytes"

    "context"

    "database/sql"

    "fmt"

    "io/ioutil"

    "time"

goracle "gopkg.in/goracle.v2"

)


func main() {

    fmt.Println("... Setting up Database Connection")

    testDb, err := sql.Open("goracle",

        "sys" +

            "/" +

            "Oracle18" +

            "@" +

            "localhost:32118" +

            "/" +

            "XE as sysdba")

    if err != nil {

        fmt.Println("... DB Setup Failed")

        fmt.Println(err)

        return

    }

    defer testDb.Close()


// Get file as bytes

dat, err := ioutil.ReadFile("./sample.png")

if err != nil {

    fmt.Println(".....Error Opening File")

    fmt.Println(err)

    return

}


// BLOB creation && passing file into it

directLob := goracle.Lob{ Reader: bytes.NewReader(dat[:])}


fmt.Println("\nINSERTING BLOB - starting....")

// Working BLOB insertion - INSERT COMMAND

_, err = testDb.Exec("insert into AA_LIVE_FRAMES(id, frame) VALUES(:1, :2)",  1, directLob)

if err != nil {

    fmt.Println(".....Error Inserting BLOB")

    fmt.Println(err)

    return

}

fmt.Println("\nINSERTING BLOB - ended.")


fmt.Println("\nSuccess")

}

这是正在运行的 main.go 文件。


较长版本的答案


如果代码如此简单,为什么我花了这么长时间?


当我开始解决这个问题时,我在 goracle 文档中没有找到任何说明如何将 BLOB 插入 OracleDB 的教程或示例。当然,这个 goracle.Lob 结构具有很好的功能 - Read()。这是我第一次尝试,声明这个 goracle.Lob 并使用它的 Read() 函数,但它给了我错误 - nil 地址等等。我不知道为什么,尝试调试它 - 没有结果。然后我更深入,我从 goracle 包中提取了一些测试代码,展示了如何创建临时 LOB - 其中一些代码显示在我的问题答案中。再次,没有成功。然后,我尝试原始 SQL,再次失败(我认为因为我的 OracleDB 是 docker - 创建目录,将 BLOB 插入 OracleDB 所需的目录不起作用;nvm)。


最后,我不知道为什么,我尝试过结构文字:


directLob := goracle.Lob{ Reader: bytes.NewReader(dat[:])}

并工作了。


好吧,为什么我要输入这些内容?因为,据我所知,这样做:


directLob := goracle.Lob{ Reader: bytes.NewReader(dat[:])}

和这个:


directLob := goracle.Lob{}

directLob.Read(dat[:])

应该是一样的吗?或者我完全错了?


查看完整回答
反对 回复 2023-07-31
  • 1 回答
  • 0 关注
  • 159 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信