Golang如何从Oracle数据库读取长二进制格式图片

Golang如何从Oracle数据库读取长二进制格式图片 我正在尝试使用Golang代码从外部Oracle数据库读取图像(long raw数据类型)。

当调用sql的row.Next()时捕获到以下错误:ORA-01406: 提取的列值被截断

row.Next在从mssql数据库读取blob图像时工作正常。

示例代码:

db, err := sql.Open("oci8", getDSN()) //获取连接详情的函数
    if err != nil {
        fmt.Println(err)
        return
    }
    defer db.Close()
    rows, err := db.Query("SELECT image FROM sysadm.all_images")
    if err != nil {
        fmt.Println(err)
        return
    }
    defer rows.Close()
    for rows.Next() {
       var id string
       var data []byte
       rows.Scan(&id, &data)    
    }
    fmt.Println("Total errors", rows.Err())
}

希望有人能帮助我解决这个问题或指出问题所在。


更多关于Golang如何从Oracle数据库读取长二进制格式图片的实战教程也可以访问 https://www.itying.com/category-94-b0.html

2 回复

gracylayla:

ORA-01406

谷歌告诉我,查询结果对程序而言过大,需要增加缓冲区大小。

但我不知道具体该如何操作。

更多关于Golang如何从Oracle数据库读取长二进制格式图片的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


ORA-01406错误通常发生在Oracle数据库中,当尝试读取超过驱动程序默认缓冲区大小的LOB(大对象)数据时。对于LONG RAW数据类型,需要使用专门的LOB处理方式。

以下是修正后的代码示例:

package main

import (
    "database/sql"
    "fmt"
    _ "github.com/mattn/go-oci8"
)

func main() {
    db, err := sql.Open("oci8", getDSN())
    if err != nil {
        fmt.Println(err)
        return
    }
    defer db.Close()

    // 使用oci8驱动程序的LOB处理功能
    rows, err := db.Query("SELECT image FROM sysadm.all_images")
    if err != nil {
        fmt.Println(err)
        return
    }
    defer rows.Close()

    for rows.Next() {
        var data []byte
        
        // 对于LONG RAW列,需要使用oci8的特殊处理
        err := rows.Scan(&data)
        if err != nil {
            fmt.Printf("Scan error: %v\n", err)
            continue
        }
        
        fmt.Printf("Read %d bytes of image data\n", len(data))
        
        // 处理图像数据,例如保存到文件
        // err = os.WriteFile("output.jpg", data, 0644)
    }

    if err := rows.Err(); err != nil {
        fmt.Printf("Rows error: %v\n", err)
    }
}

如果上述方法仍然遇到问题,可以尝试使用Oracle的LOB函数进行转换:

// 方法2:使用TO_LOB转换LONG RAW为BLOB
rows, err := db.Query("SELECT TO_LOB(image) FROM sysadm.all_images")
if err != nil {
    fmt.Println(err)
    return
}

或者使用分段读取的方式:

// 方法3:分段读取大对象数据
var chunk []byte
var totalData []byte

// 假设你知道大概的块大小,或者使用循环读取
for {
    err := db.QueryRow(`
        SELECT DBMS_LOB.SUBSTR(image, 4000, ?) 
        FROM sysadm.all_images WHERE id = ?`, 
        offset, imageID).Scan(&chunk)
    if err != nil {
        break
    }
    if len(chunk) == 0 {
        break
    }
    totalData = append(totalData, chunk...)
    offset += len(chunk)
}

确保你的Oracle驱动程序支持LOB操作。对于github.com/mattn/go-oci8驱动程序,需要正确配置OCI环境来处理大对象数据。

回到顶部