英文:
Unsupported Scan: SQL UUID Array
问题
我正在尝试从 PostgreSQL 数据库中获取一个 UUID
数组,但是出现了以下错误:
sql: 在索引为 0 的列上扫描错误:不支持的扫描,将 driver.Value 类型的 []uint8 存储到类型为 *[]string 的变量中
获取单个 UUID
没有问题,但是当它是一个数组时,Scan
函数将元素的类型推断为 uint8
。
是否有解决这个问题的方法?或者我应该重新考虑我的数据库设计?
代码:
func FetchListIdsForUser(id string, db *sql.DB) ([]string, error) {
// 存储结果的变量
var (
lists []string
)
// 准备语句
stmt, err := db.Prepare("select lists from users where object_id = $1")
if err != nil {
formattedError := er.New("FetchListIdsForUser SQL Select: " + err.Error())
log.Println(formattedError)
return nil,formattedError
}
defer stmt.Close()
// 执行查询
rows, err := stmt.Query(id)
if err != nil {
formattedError := er.New("FetchListIdsForUser SQL Query: " + err.Error())
log.Println(formattedError)
return nil,formattedError
}
defer rows.Close()
// 遍历每一行
for rows.Next() {
// 扫描:这是出错的地方
err := rows.Scan(&lists)
if err != nil {
formattedError := er.New("FetchListIdsForUser SQL Scan: " + err.Error())
log.Println(formattedError)
return nil,formattedError
}
return lists,nil
}
err = rows.Err()
if err != nil {
formattedError := er.New("FetchListIdsForUser: " + id + " Does Not Exist")
log.Println(formattedError)
return nil,formattedError
}
return nil,er.New("FetchListIdsForUser: " + id + " Does Not Exist")
}
英文:
I am trying to get an array of UUID
from a PostgreSQL DB, this gives the following error:
sql: Scan error on column index 0: unsupported Scan, storing driver.Value type []uint8 into type *[]string
Fetching a single UUID
is no problem, but when it is an array
, the Scan
function infers the type of the elements as uint8
.
Is there a workaround / solution for this? Or should I rethink my DB?
Code :
func FetchListIdsForUser(id string, db *sql.DB) ([]string, error) {
// where the results will be stored
var (
lists []string
)
// statement prep
stmt, err := db.Prepare("select lists from users where object_id = $1")
if err != nil {
formattedError := er.New("FetchListIdsForUser SQL Select: " + err.Error())
log.Println(formattedError)
return nil,formattedError
}
defer stmt.Close()
// query happening
rows, err := stmt.Query(id)
if err != nil {
formattedError := er.New("FetchListIdsForUser SQL Query: " + err.Error())
log.Println(formattedError)
return nil,formattedError
}
defer rows.Close()
// for each row
for rows.Next() {
// scan : this is where the error happens.
err := rows.Scan(&lists)
if err != nil {
formattedError := er.New("FetchListIdsForUser SQL Scan: " + err.Error())
log.Println(formattedError)
return nil,formattedError
}
return lists,nil
}
err = rows.Err()
if err != nil {
formattedError := er.New("FetchListIdsForUser: " + id + " Does Not Exist")
log.Println(formattedError)
return nil,formattedError
}
return nil,er.New("FetchListIdsForUser: " + id + " Does Not Exist")
}
答案1
得分: 1
你的代码可以简化很多:
func FetchListIdsForUser(id string, db *sql.DB) ([]string, error) {
rows, err := db.Query("SELECT unnest(lists) FROM users WHERE object_id = $1", id)
if err != nil {
formattedError := errors.New("FetchListIdsForUser SQL Query: " + err.Error())
return nil, formattedError
}
defer rows.Close()
var lists []string
var list string
for rows.Next() {
// scan every item of the array and append it to lists
err := rows.Scan(&list)
if err != nil {
formattedError := errors.New("FetchListIdsForUser SQL Scan: " + err.Error())
return nil, formattedError
}
lists = append(lists, list)
}
if lists == nil {
// no rows returned
formattedError := errors.New("FetchListIdsForUser: " + id + " Does Not Exist")
return nil, formattedError
}
return lists, nil
}
db.Query()
会为你准备(并缓存)语句,不需要手动执行。- 我在 select 语句中添加了
unnest(lists)
。这将为数组中的每个元素生成一行。 - 在循环中,我们逐个扫描每个元素并将其追加到
lists
中。
此外,这个驱动程序可以直接支持扫描数组。
英文:
Your code can be simplified a lot:
func FetchListIdsForUser(id string, db *sql.DB) ([]string, error) {
rows, err := db.Query("SELECT unnest(lists) FROM users WHERE object_id = $1", id)
if err != nil {
formattedError := errors.New("FetchListIdsForUser SQL Query: " + err.Error())
return nil, formattedError
}
defer rows.Close()
var lists []string
var list string
for rows.Next() {
// scan every item of the array and append it to lists
err := rows.Scan(&list)
if err != nil {
formattedError := errors.New("FetchListIdsForUser SQL Scan: " + err.Error())
return nil,formattedError
}
lists = append(lists, list)
}
if lists == nil {
// no rows returned
formattedError := errors.New("FetchListIdsForUser: " + id + " Does Not Exist")
return nil, formattedError
}
return lists, nil
}
db.Query()
will prepare (and cache) the statement for you. There's no need to do that manually.- I added
unnest(lists)
to the select statement. This will produce one row for every element in the array. - In the for loop, we scan every element individually and append it to
lists
.
Also, this driver supports scanning arrays out of the box.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论