golang sqlx "missing destination name ...."

14

当我使用sqlx与postgresql时,出现错误:"缺少目标名称rec_created_by"

type Client struct {
    ClientID                    string          `json:"client_id"   db:"id"`
    Name                        string          `json:"name"    db:"name"`
    Version                     int16           `json:"version" db:"version"`
    IsActivated                 bool            `json:"is_activated"    db:"is_activated"`
    RecCreatedBy                string          `json:"rec_created_by"  db:"rec_created_by"`
    RecCreatedByUser            *User           `json:"rec_created_by_user" db:"-"`
    RecCreated                  *time.Time      `json:"rec_created" db:"rec_created"`
    RecModifiedBy               string          `json:"rec_modified_by" db:"rec_modified_by"`
    RecModifiedByUser           *User           `json:"rec_modified_by_user"    db:"-"`
    RecModified                 *time.Time      `json:"rec_modified"    db:"rec_modified"`
    CultureID                   string          `json:"culture_id"  db:"culture_id"`
    ...
}
func (c *Client) Get(id string) error {
    db, err := sqlx.Connect(settings.Settings.Database.DriverName, settings.Settings.GetDbConn())
    if err != nil {
        log.Fatal(err)
    }
    defer db.Close()
    _client := Client{}
    err = db.QueryRowx("SELECT id, name, version, is_activated, rec_created_by, rec_created, rec_modified_by, rec_modified, culture_id, amount_decimal_places, amount_rounding_precision, \"unit-amount_decimal_places\", \"unit-amount_rounding_precision\", currency_lcy_id  FROM client WHERE id=$1", id).StructScan(&_client)
    if err == sql.ErrNoRows {
        return ErrClientNotFound
    } else if err != nil {
        return err
    }
    return nil
 }

我在我的客户端类型中有db:"rec_created_by",但为什么会出现错误。


它并不能解决这个问题,但如果你在使用Go处理数据库,可以看一下GORM。它支持postgresql。 - T. Claverie
我有一个问题,如果这是在*Client上的一个方法,为什么你在方法体内创建了一个_client := &Client{},然后似乎什么也没做。 - Snowman
我只是为了测试添加了_client。 - Tuan Hoang Anh
你的代码看起来很好,所以我没有什么“修复”可以提供,但为了进一步调试...你是否尝试从查询中删除该列名称,以查看是否会出现其他列的相同错误? - semi
我已经更改了数据库和结构:rec_created -> rec_created_at,rec_modified -> rec_modified_at,现在它可以工作了。 - Tuan Hoang Anh
1个回答

11

对于遇到类似问题的人,这里有几个可能的原因。

TL;DR

  1. 结构体字段未导出。
  2. 结构体标签语法无效。
  3. 查询结果列名与结构体标签不匹配。

结构体字段未导出

为了能够被sqlx进行编组和解组,结构体字段必须被导出。

type foo struct {
    bar string `db:"bar"` // This wont work. 'bar' needs to be 'Bar'
}

结构体标签无效

是的。我已经做了所有这些事情。

type Foo struct {
    bar string `db="bar"` // Should be : not =
}
type Foo struct {
    bar string `json:"bar", db:"bar"` // There should not be a comma
}

查询结果列名不匹配

type foo struct {
    BarName string `db:"bar_name"`
}

myfoo := foo{}
db.Get(&myfoo, `SELECT barname FROM foo_table WHERE barname = 'bar string'`)
// This will fail because the returned column is missing the '_'
type foo struct {
    Bar string `db:"Bar"`
}

myfoo := foo{}
db.Get(&myfoo, `SELECT Bar FROM foo_table WHERE Bar = 'bar string'`)
// This will fail because the returned column is actually 'bar'.

Postgres 区分大小写。因此,Barbar 不相同。

您可以使用大写标识符,但必须用双引号括起来。

myfoo := foo{}
db.Get(&myfoo, `SELECT "Bar" FROM foo_table WHERE "Bar" = 'bar string'`)

当然,如果您是使用“IF NOT EXISTS”选项创建表的...

CREATE TABLE foo_table
(
    Bar TEXT NOT NULL
)

嗯...该列实际上将被命名为bar。这是因为Postgres会将所有未引用的标识符转换为小写。

您可以通过以下方法解决此问题:

  1. 更改结构标记中的大小写。
  2. 重命名数据库中的列。(可能仅适用于开发早期阶段)
  3. 在查询中使用别名。

我们可以通过以下方式编写查询来解决上述问题...

type foo struct {
    Bar string `db:"FooBar"`
}

myfoo := foo{}
db.Get(&myfoo, `SELECT bar as "FooBar" FROM foo_table WHERE bar = 'bar string'`)
// This will work because we have renamed the returned column to "FooBar".

在我的情况下,一切都是正确的,但它仍然无法工作。然而,我正在使用Clickhouse驱动程序,所以这可能是一个错误。 - Matteo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接