我有一个带有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)
说:
最佳答案
经过数十个小时的尝试,试图弄清楚如何使用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)。
最后,我不确定为什么,我尝试了structliteral:
directLob := goracle.Lob{ Reader: bytes.NewReader(dat[:])}
和工作。
好吧,为什么我要输入所有这些?因为,AFAIK,这样做:
directLob := goracle.Lob{ Reader: bytes.NewReader(dat[:])}
还有这个:
directLob := goracle.Lob{}
directLob.Read(dat[:])
应该一样吗?还是我完全错了?