golang mysql在结构中存储了任意数量的行

问题描述 投票:0回答:1

所以我有一个看起来像这样的SQL

SELECT accounts.id, accounts.username, accounts.password, 
      accounts.created, accounts.last_logged_in, accounts.access,
      banned.reason, banned.expires,
      player.x, player.y, player.zone
FROM accounts
LEFT JOIN banned
ON accounts.id = banned.account_Id
INNER JOIN player
ON accounts.id = player.account_Id
WHERE accounts.username = username

如果我想将它存储在一个结构中,我通常会这样做:

type Account struct {
    Id           int
    Username     string
    Password     string
    Email        string
    Created      time.Time
    LastLoggedIn time.Time
    AccessLevel  int
    Location     struct {
        Zone string
    }
    Banned []*Banned
}

type Banned struct {
    Reason  string
    Expires time.Time
}
reply := new(Account)

stmt, err := this.Database.Prepare(("CALL findUser(?)"))
    defer stmt.Close()

if err != nil {
    logger.ERROR.Println(err)
    return err
}

err = stmt.QueryRow(args).Scan(&reply.Id, &reply.Username ... you get the idea)

但是这不起作用,因为扫描会期望每个参数都有一个值,而我们已经加入了被禁止的状态!由于用户可能有0 - N禁止什么是解决这个问题的最佳方法?

非常感谢Zidsal

mysql go
1个回答
2
投票

我觉得你的例子或问题不是你真正想要描述的,因为他们并没有真正要求同样的问题。

阅读提供的示例,您有两种不同的类型要扫描(Account,左连接Banned),将对结果的每一行重复。所以你必须在你的Banned结构的同时创建一个新的Account结构并使用它来扫描值,然后将它添加到Account.Banned切片。循环每一行,你就完成了。

阅读你的问题,我认为你的SQL查询有些错误:你有多个帐户,每个帐户都有几个禁令,并且你希望在结果行中有一个帐户,每个禁令都在其中。要做到这一点,你需要用GROUP BY语句调整你的查询以获得一行的帐户,然后最聪明的方法是做一个GROUP_CONCAT将每个禁令变成一个属性,然后你可以相应地解析。示例(过度简化以更好地暴露原理):

  SELECT accounts.id, GROUP_CONCAT(banned.id SEPARATOR ',') as bans
  FROM accounts
  LEFT JOIN banned
  ON accounts.id = banned.account_Id
  WHERE accounts.username = username
  GROUP BY accounts.id

你只需要将bans列扫描成一个字符串,将它拆分为,等。在你的情况下,解析会更复杂,因为你需要在一列中有2个值,但原理是相同的。

© www.soinside.com 2019 - 2024. All rights reserved.