【问题标题】:How to properly scan the results of the array_agg function in Golang?如何正确扫描Golang中array_agg函数的结果?
【发布时间】:2021-07-04 02:10:27
【问题描述】:

在我的 Golang (1.15) 应用程序中,我使用 sqlx 包来处理 PostgreSQL 数据库 (PostgreSQL 12.5)。

我的 SQL 请求有一个 array_agg 函数,该函数返回字符串数组,如果为空则返回 null。

我正在尝试Scan 这个 SQL 请求的结果,但它在我的程序中引发了下一个错误:

sql:列索引 3 上的扫描错误,名称为“organization_ids”: 不支持扫描,将 driver.Value 类型字符串存储为 *[]string

类型

代码 sn-p:

type Channel struct {
    ChannelId           *string   `db:"channel_id" json:"channelId"`
    ChannelName         *string   `db:"channel_name" json:"channelName"`
    OrganizationsIds    *[]string `db:"organizations_ids" json:"organizationsIds"`
}

var channel Channel

row := db.QueryRow(`
    select
        channels.channel_id::text,
        channels.channel_name::text,
        array_agg(distinct channels_organizations_relationship.organization_id)::text[] organizations_ids
    from
        channels
    left join channels_organizations_relationship on
        channels.channel_id = channels_organizations_relationship.channel_id
    where
        channels.channel_id = $1
    group by
        channels.channel_id
    limit 1;`, *channelId)

if err := row.Scan(&channel.ChannelId, &channel.ChannelName, &channel.OrganizationsIds); err != nil {
    fmt.Println(err)
}

return &channel

我还尝试将Channel结构中OrganizationsIds字段的数据类型更改为github.com/lib/pq包中的*pg.StringArray。在这种情况下,当我Scan 时,我的程序中出现以下错误:

sql:列索引 3 上的扫描错误,名称为“organizations_ids”: 不支持扫描,将 driver.Value 类型字符串存储到类型中 *[]pq.StringArray

我的任务是为此列向客户端返回一个字符串列表或 null/nil。

有人可以解释如何解决这种奇怪的行为吗?

【问题讨论】:

  • pq.StringArray 的基础类型是[]string,因此您可以做的一件事是在扫描之前将您的字段转换为pq.StringArray。即字段为OrganizationsIds []string,然后在扫描时执行row.Scan(..., (*pq.StringArray)(&channel.OrganizationIds))
  • ... 或使用 OrganizationsIds pq.StringArray 然后在扫描中:row.Scan(..., &channel.OrganizationIds)
  • 你好@mkopriva!谢谢您的回答。事实上,我已经检查了您推荐的两个选项。它仅在列返回字符串数组时才有效。当此列为空并返回 null 时,您的建议会引发错误。错误如下所示:sql: Scan error on column index 3, name "organizations_ids": pq: parsing array element index 0: cannot convert nil to string。您对如何解决它有任何想法吗?
  • 这是数组中的单个 id 为 NULL 而不是整个数组,要使其工作,您必须使用 []*string[]sql.NullString 作为目标类型。尝试pq.Array 函数,例如拥有OrganizationsIds []*string 并像这样扫描row.Scan(..., pq.Array(&channel.OrganizationIds))
  • 好吧,我又检查了一遍。我的 SQL 请求返​​回一个包含一个空值 {NULL} 的数组。看来我需要更改请求本身。你怎么看?

标签: sql postgresql go


【解决方案1】:

好吧,我终于找到了我的问题的解决方案。

我注意到array_agg 函数返回[null]。我稍微更改了 SQL 请求以返回 null 而不是 [null]。我通过这些更改做到了:

array_agg(distinct channels_organizations_relationship.organization_id) filter (where channels_organizations_relationship.organization_id is not null)

在这篇文章 (Postgres returns [null] instead of [] for array_agg of join table ) 中,您可以找到许多不同的解决方案。

那么您可以使用以下解决方案之一:

第一个选项

我们可以在结构体中使用OrganizationsIds pq.StringArray,然后在扫描时使用 row.Scan(..., &channel.OrganizationIds

第二个选项

我们可以在结构体中使用OrganizationsIds []string,然后在扫描时使用row.Scan(..., (*pq.StringArray)(&channel.OrganizationIds))

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-24
    • 2023-02-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-15
    相关资源
    最近更新 更多