首页 > 解决方案 > Golang SQL 表加入切片字段

问题描述

考虑下表

CREATE TABLE foo (
  id INT PRIMARY KEY
)

CREATE TABLE bar (
  id INT PRIMARY KEY
)

CREATE TABLE foo_bar_members (
  foo_id INT NOT NULL REFERENCES foo(id) ON DELETE CASCADE ON UPDATE CASCADE,
  bar_id INT NOT NULL REFERENCES bar(id) ON DELETE CASCADE ON UPDATE CASCADE,
  PRIMARY KEY (foo_id, bar_id)
)

foo_bar_members是连接foo和的关系表barfoo作为 的父级查看bar。我有以下 Go 结构:

type Foo struct {
  ID     int `db:"id"`
  BarIDs []int
}

BarIDsbar.id与 this 相关联foo的一部分foo.id。我想查询这样的事情:

SELECT * FROM foo f INNER JOIN foo_bar_members fbm ON f.id = fbm.foo_id WHERE f.id = $1

但是这个查询只是一个例子。显然这不会扫描到Foo.BarIDs. 我总是可以做两个单独的查询,但我想知道是否有更好的方法。我正在使用sqlx

标签: sqlpostgresqlgo

解决方案


SQL,这里的左连接也将返回没有关联条的 foos。

select
    foo.id
    , array_agg(bar.id)
from foo
left join foo_bar_members m on m.foo_id = foo.id
where foo.id = $1
group by foo.id

如果你只关心有 bar 的 foos,那么实际上就不需要 join。

select
    m.foo_id
    , array_agg(m.bar_id)
from foo_bar_members m
where m.foo_id = $1
group by m.foo_id

去代码:

const sql = "<one of the queries from above>"

f := new(Foo)
if err := db.QueryRow(sql, 123).Scan(&f.ID, pq.Array(&f.BarIDs)); err != nil {
    return err
}

pq.Array是一个函数,它返回一个实现sql.Scanneranddriver.Valuer接口的值,并且实现知道如何将 postgres 数组扫描到 go slice 或将 go slice 转换为 postgres 数组。


我不熟悉,sqlx所以它本身可能提供了一些允许您扫描数组的功能,因此pq.Array可能不需要使用。也许更了解的人最终会提供他们的解决方案版本。


推荐阅读