【问题标题】:Multiple rows.Next() in the same time golang sql/database多行.Next() 在同一时间 golang sql/database
【发布时间】:2018-09-15 11:07:42
【问题描述】:

我正在开发一个吸引用户的功能。我的问题是我必须将两个查询的结果作为rows.Next()rows1.Next() 中的一个结果返回,例如user_idsubjectphone

这是我所拥有的,但它不起作用。你能帮我提些建议吗:

func GetUsers() (users []Users, err error) {

    users = make([]Users, 0)
    rows, err := db1.Query("SELECT  user_id, subject,phone FROM users limit 11")
    rows1, err := db1.Query("Select body from users limit 11")
    defer rows.Close()
    if err != nil {
        // handle this error better than this
        log.Fatal(err)
        //return
    }
    var user Users
    for rows.Next() {
        rows.Scan(&user.ID, &user.Subject, &user.Phone)
        users = append(users, user)
    }
    for rows1.Next() {

        rows1.Scan(&user.Body)
        users = append(users, user)

    }
    return 
}

我有一个名为users 的表,它基本上没有主键:

user_id . name  . body 
-----------------------
1       . model . 2
1       . brand . 1
1       . fuel  . 3
1       . date  . 1
1       . year  . 1

我必须有结果:

userid . model . brand . fuel . date . year 
1      . 2     . 1     . 3    . 1    . 1

所以列名中的值将是行。我已经定义了包含所有需要的字段的结构。

【问题讨论】:

  • 你能扩展“它不起作用”吗?您面临的具体问题是什么?
  • 您怎么知道您在第二个查询中返回的body 将与第一个查询中的user_id 对应?为什么不在第一个查询中检索body。你在做什么有点奇怪,似乎会导致很多奇怪的问题。
  • 我的问题是我必须将 rows.Next() 合并为 query1 获取 id,subject,phone 与 rows1.Next() 获取正文以获得包含所有字段的结果我希望它是清除 @Adrian 先生,谢谢
  • @Medone 您在两个查询中查询同一个表,只需在一个查询中执行,您的问题就解决了。
  • 目前还不清楚为什么。只需将body 添加到您的第一个查询中。它来自同一张表,因此用户的关系已经存在。然后一次将所有四个属性添加到users.user

标签: mysql go struct slice


【解决方案1】:

查看示例代码很明显,您应该在一个查询而不是两个查询中执行您正在执行的任何操作。即使您的实际代码稍有不同,假设您需要查询多个表,您仍然应该使用 JOIN 只执行一个查询。

users := make([]*User, 0)
rows, err := db1.Query("SELECT  user_id, subject,phone, body FROM users limit 11")
if err != nil {
    log.Fatal(err)
}
defer rows.Close()

for rows.Next() {
    user := new(User)
    if err := rows.Scan(&user.ID, &user.Subject, &user.Phone, &user.Body); err != nil {
        panic(err)
    }       
    users = append(users, user)
}
if err := rows.Err(); err != nil {
    panic(err)
}

也就是说,如果您想按照您在问题中说明的方式进行操作,您可以这样做。

(这可能不是你应该做的)

users := make([]*User, 0)
rows, err := db1.Query("SELECT  user_id, subject,phone FROM users limit 11")
if err != nil {
    log.Fatal(err)
}
defer rows.Close()

rows1, err := db1.Query("Select body from users limit 11")
if err != nil {
    panic(err)
}
defer rows1.Close()

for rows.Next() {
    user := new(User)
    if err := rows.Scan(&user.ID, &user.Subject, &user.Phone); err != nil {
        panic(err)
    }
    if !rows1.Next() {
        panic("no next body row")
    }
    if err := rows1.Scan(&user.Body); err != nil {
        panic(err)
    }

    users = append(users, user)
}
if err := rows.Err(); err != nil {
    panic(err)
}
if err := rows1.Err(); err != nil {
    panic(err)
}

【讨论】:

  • 非常感谢@mkopriva 这是我一直在寻找的东西
【解决方案2】:
const maxPerPage = 100

type Scanable interface {
    GetScans() []interface{}
}

type User struct {
    ID      int
    Subject string
    Phone   string
    Body    string
}

func (s *User) GetScans() []interface{} {
    return []interface{}{&s.ID, &s.Subject, &s.Phone, &s.Body}
}

func getNewUserList() []*User {
    users := make([]*User, maxPerPage)
    for i := 0; i < maxPerPage; i++ {
        users[i] = new(User)
    }
    return users
}

var usersPool = sync.Pool{
    New: func() interface{} {
        return getNewUserList()
    },
}

func getUsers() (b []*User) {
    ifc := usersPool.Get()
    if ifc != nil {
        b = ifc.([]*User)
    } else {
        b = getNewUserList()
    }
    return
}

func putUsers(b []*User) {
    // if cap(b) <= maxPerPage {
    //     b = b[:0] // reset
    //     usersPool.Put(&b)
    // }
    usersPool.Put(&b)
}

func TestUsers(t *testing.T) {

    users := getUsers()

    rows, err := PostgresConnection.Query("SELECT user_id, subject,phone, body FROM users limit 11")
    if err != nil {
        log.Fatal(err)
    }
    defer rows.Close()

    length := 0
    for rows.Next() {
        if err := rows.Scan(users[i].GetScans()...); err != nil {
                panic(err)
            }
            if err := rows.Err(); err != nil {
                panic(err)
            }
        length++
    }

    result := users[:length]
    fmt.Println(result)

    putUsers(users)
}

【讨论】:

  • 您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center
猜你喜欢
  • 2017-07-28
  • 2021-08-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-12-10
  • 1970-01-01
  • 1970-01-01
  • 2020-08-20
相关资源
最近更新 更多