从数据库表中扫描[]byte数据的Golang实现方法
从数据库表中扫描[]byte数据的Golang实现方法 我的表结构中有一个blob列,对应的是[]byte类型。当我尝试扫描它时,显示----- 不支持的列类型 -98 ----- 这是什么意思,能给我解释一下吗?
提前感谢。
谢谢。
非常感谢。
好的,谢谢。
你知道 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中看到这些include和constants(注意这里没有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,不过 binary、varbinary 和 longvarbinary 应该被支持:
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 的具体原因取决于你使用的数据库类型和驱动版本。建议:
- 确保使用最新版本的数据库驱动
- 检查数据库列的实际类型是否与驱动支持的类型匹配
- 对于 MySQL,BLOB 类型应该能正确映射到 []byte
- 对于 PostgreSQL,使用 bytea 类型而不是 BLOB
如果问题仍然存在,请提供你使用的具体数据库类型和驱动版本,以便进一步诊断。

