从数据库表中扫描[]byte数据的Golang实现方法

从数据库表中扫描[]byte数据的Golang实现方法 我的表结构中有一个blob列,对应的是[]byte类型。当我尝试扫描它时,显示----- 不支持的列类型 -98 ----- 这是什么意思,能给我解释一下吗?

提前感谢。

16 回复

谢谢

更多关于从数据库表中扫描[]byte数据的Golang实现方法的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


谢谢。

@iegomez

非常感谢。

好的,谢谢。

你知道 go get 是如何工作的吗?我们能否控制这个过程?

SQL_BLOB 就是 SQL_LONGVARBINARY,它明明在 switch case 中,但为什么找不到呢。

我们需要您提供更多信息以便能够帮助您:

您正在使用哪种关系型数据库管理系统?您使用的是哪个驱动程序?您是否检查过它的文档(很可能不支持二进制大对象)?等等。

所需类型是切片,但你提供的是数组。尝试定义一个容量为5的切片并将其作为参数传递

v := make([]uint8, 0, 5)

来自 database/sql 包:

sql 包必须与数据库驱动程序配合使用。有关驱动程序列表,请参阅 Go Wiki: SQL Database Drivers - The Go Programming Language

那么,具体是哪个驱动程序呢?还是您在使用其他东西?

如果你指的是这个主题,或者这个主题,请将相关讨论保留在原处。请不要在不相关的主题中混入讨论。

@iegomez  
我刚刚在 column.go 和 api_windows.go 文件中添加了 SQL_BLOB,然后出现了  
"sql: Scan error on column index 0: unsupported Scan, storing driver.Value type []uint8 into type *[5]uint8"  
这类错误,你知道该如何处理这个错误吗?

是的!我正在使用 Db2(IBM 数据库),并创建了一个列类型为 blob 的表,该列可以存储字节数组。现在我使用 QueryRow 来扫描该值,但返回了“不支持的列类型 -98”。

_,err=db.Query("create table byt1(name blob(5))")

插入命令…然后

var a [5]byte
err = db.QueryRow("select name from byt1").Scan(&a)

现在它返回“不支持的列类型 -98”。

这取决于被调用的C API。你可能会在db2cli/api/api_unix.go中看到这些includeconstants(注意这里没有BLOB):

// #include <sqlcli1.h>

...
const(
...
	SQL_BINARY          = C.SQL_BINARY
	SQL_VARBINARY       = C.SQL_VARBINARY
	SQL_LONGVARBINARY   = C.SQL_LONGVARBINARY
...
)

如果你搜索该头文件,第一个结果显示BLOB是有效的数据类型,但没有提到BINARY类型:

/* SQL extended data types */
#define  SQL_GRAPHIC            -95
#define  SQL_VARGRAPHIC         -96
#define  SQL_LONGVARGRAPHIC     -97
#define  SQL_BLOB               -98
#define  SQL_CLOB               -99

还要注意-98与你错误中的列类型匹配。

所以看起来很久以前sqlcli1.h头文件声明了二进制类型,而现在声明了blob类型,它们之间的值不匹配。因此过时的驱动程序正确地报告列类型未知,因为它没有实现新的API。换句话说,在这种情况下,BLOB不会转换为LONGVARBINARY

如果你想的话可以自己修补这个问题(尽管你可能会发现很多这样的错误需要修复才能让驱动程序工作),但我建议你找一个更新的、有维护的驱动程序。

检查 column.go 中的代码,NewColumn 函数似乎不支持 blobs,不过 binaryvarbinarylongvarbinary 应该被支持:

    switch sqltype {
	case api.SQL_BIT:
		return NewBindableColumn(b, api.SQL_C_BIT, 1), nil
	case api.SQL_TINYINT, api.SQL_SMALLINT, api.SQL_INTEGER:
		return NewBindableColumn(b, api.SQL_C_LONG, 4), nil
	case api.SQL_BIGINT:
		return NewBindableColumn(b, api.SQL_C_SBIGINT, 8), nil
	case api.SQL_NUMERIC, api.SQL_DECIMAL, api.SQL_FLOAT, api.SQL_REAL, api.SQL_DOUBLE:
		return NewBindableColumn(b, api.SQL_C_DOUBLE, 8), nil
	case api.SQL_TYPE_TIMESTAMP:
		var v api.SQL_TIMESTAMP_STRUCT
		return NewBindableColumn(b, api.SQL_C_TYPE_TIMESTAMP, int(unsafe.Sizeof(v))), nil
	case api.SQL_TYPE_DATE:
		var v api.SQL_DATE_STRUCT
		return NewBindableColumn(b, api.SQL_C_DATE, int(unsafe.Sizeof(v))), nil
	case api.SQL_CHAR, api.SQL_VARCHAR:
		return NewVariableWidthColumn(b, api.SQL_C_CHAR, size), nil
	case api.SQL_WCHAR, api.SQL_WVARCHAR:
		return NewVariableWidthColumn(b, api.SQL_C_WCHAR, size), nil
	case api.SQL_BINARY, api.SQL_VARBINARY:
		return NewVariableWidthColumn(b, api.SQL_C_BINARY, size), nil
	case api.SQL_LONGVARCHAR:
		return NewVariableWidthColumn(b, api.SQL_C_CHAR, 0), nil
	case api.SQL_WLONGVARCHAR, api.SQL_SS_XML:
		return NewVariableWidthColumn(b, api.SQL_C_WCHAR, 0), nil
	case api.SQL_LONGVARBINARY:
		return NewVariableWidthColumn(b, api.SQL_C_BINARY, 0), nil
	default:
		return nil, fmt.Errorf("unsupported column type %d", sqltype)
	}

话虽如此,您使用的驱动程序已经超过三年没有更新了,所以我建议寻找一个新的、希望有人维护的驱动程序(我不使用 DB2,所以不知道哪个能帮上忙)。

这个错误通常发生在数据库驱动无法识别特定的列类型时。错误代码 -98 表示驱动遇到了它不支持的列类型。对于 BLOB 列,你需要确保正确使用数据库驱动和扫描方法。以下是几种常见数据库的实现示例:

使用 database/sql 标准库的示例:

import (
    "database/sql"
    _ "github.com/go-sql-driver/mysql" // MySQL 驱动
)

type MyStruct struct {
    ID   int
    Data []byte
}

func main() {
    db, err := sql.Open("mysql", "user:password@/dbname")
    if err != nil {
        panic(err)
    }
    defer db.Close()

    var result MyStruct
    err = db.QueryRow("SELECT id, blob_column FROM my_table WHERE id = ?", 1).Scan(&result.ID, &result.Data)
    if err != nil {
        panic(err)
    }
}

使用 GORM 的示例:

import (
    "gorm.io/driver/mysql"
    "gorm.io/gorm"
)

type MyModel struct {
    ID   uint `gorm:"primaryKey"`
    Data []byte
}

func main() {
    dsn := "user:password@tcp(127.0.0.1:3306)/dbname?charset=utf8mb4&parseTime=True&loc=Local"
    db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
    if err != nil {
        panic(err)
    }

    var result MyModel
    db.First(&result, 1)
}

处理 PostgreSQL bytea 列的示例:

import (
    "database/sql"
    _ "github.com/lib/pq"
)

func main() {
    db, err := sql.Open("postgresql", "postgres://user:password@localhost/dbname?sslmode=disable")
    if err != nil {
        panic(err)
    }
    defer db.Close()

    var data []byte
    err = db.QueryRow("SELECT bytea_column FROM my_table WHERE id = $1", 1).Scan(&data)
    if err != nil {
        panic(err)
    }
}

错误 -98 的具体原因取决于你使用的数据库类型和驱动版本。建议:

  1. 确保使用最新版本的数据库驱动
  2. 检查数据库列的实际类型是否与驱动支持的类型匹配
  3. 对于 MySQL,BLOB 类型应该能正确映射到 []byte
  4. 对于 PostgreSQL,使用 bytea 类型而不是 BLOB

如果问题仍然存在,请提供你使用的具体数据库类型和驱动版本,以便进一步诊断。

回到顶部