所以我有一个看起来像这样的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
我觉得你的例子或问题不是你真正想要描述的,因为他们并没有真正要求同样的问题。
阅读提供的示例,您有两种不同的类型要扫描(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个值,但原理是相同的。