【问题标题】:How to insert image as BLOB into Oracle Database如何将图像作为 BLOB 插入 Oracle 数据库
【发布时间】:2020-02-25 19:48:29
【问题描述】:

我有一个带有 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.Lob
if _, 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 值不存在

【问题讨论】:

    标签: oracle go blob


    【解决方案1】:

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

    TL;DR

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

    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() 函数,但它给了我错误 - 无地址等等。我不知道为什么,试图调试它 - 没有结果。然后我更深入,我从 goracle 包中提取了一些测试代码,展示了如何创建临时 LOB - 其中一些代码显示在我的问题答案中。再次,没有成功。然后,我尝试原始 SQL,再次失败(我认为是因为我的 OracleDB 是 docker - 创建目录,将 BLOB 插入 OracleDB 所需的目录不起作用;nvm)。

    最后,我不知道为什么,我尝试了 struct literal:

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

    并且工作了。

    好吧,为什么我要输入所有这些?因为,AFAIK,这样做:

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

    还有这个:

    directLob := goracle.Lob{}
    directLob.Read(dat[:])
    

    应该是一样的吧?还是我完全错了?

    【讨论】:

      猜你喜欢
      • 2017-03-23
      • 2017-03-26
      • 1970-01-01
      • 2014-11-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多