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

标签 oracle go blob

我有一个包含 A_LOB_TABLE 表的数据库:

enter image description here

我想使用 goracle 包将具有任意 ID(假设为“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: nonexistent LOB value

最佳答案

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

TL;博士

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

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[:])

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

关于oracle - 如何将图像作为 BLOB 插入 Oracle 数据库,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58626608/

相关文章:

java - 如何使用 Java JDBC 从数据库中获取所有触发器名称?

go - 在本地使用带有 go mod 的子包

go - 为 Linux 和 Mac 构建一个 go 二进制文件

mysql - 显示MySQL数据库中保存为base64/blob的图像

sql - 加入聚簇表比非聚簇表成本更高?

string - 在 Oracle 10g 上创建聚合函数返回无用的错误

sql - 通过 SQL LOADER 存储日期和时间值

go - 查找文本中出现次数最多的字符

由于 BLOB 字段(不能在另一个表中移动),MySQL 查询非常慢

javascript - 在javascript中压缩一个blob