Can Go's Rows.Scan ignore fields from SQL query
Asked Answered
A

2

6

The Rows.Scan method takes as many parameters as there are columns in the SQL query.

As the query being executed is SHOW COLUMNS FROM my_table I cannot omit any column which I don't require (or can I?).

Is there any way to ignore some fields from the query result set which is not required?

Below is my code:

rows, err := db.Query("SHOW COLUMNS FROM " + r.Name)
DieIf(err)
//var field, dataType, ignoreMe1, ignoreMe2, ignoreMe3 string
var field, dataType string
for rows.Next() {
                    //This Place
                    //   |
                    //   V
    if err := rows.Scan(&field, &dataType); err != nil {
        DieIf(err)
    }
    r.Attributes[field] = Attribute{
        Name:       field,
        DataType:   dataType,
        Constraint: false,
    }
}

error: sql: expected 5 destination arguments in Scan, not 2

Aishaaisle answered 6/10, 2018 at 13:55 Comment(4)
you can not ignore, if the selected fields count 5 then you have to pass 5 variable to scan in scan() , if you want scan only two values then you can write query like select field, type from <tableName>Undistinguished
I cannot pass field names in SHOW COLUMNS QUERY.Aishaaisle
so you can use `[]interface' to get that values and use according to your requirement.Undistinguished
i've attached code below, try this one, hope you will get your point.Thanks.Undistinguished
U
4

So here I'm with one solution for you, try this one to get field and type from query.

package main

import (
    "fmt"
    _ "github.com/lib/pq"
    "database/sql"
)

func main() {

    db, _ := sql.Open(
        "postgres",
        "user=postgres dbname=demo password=123456")

    rows, _ := db.Query("SELECT * FROM tableName;")

    columns, _ := rows.Columns()
    count := len(columns)
    values := make([]interface{}, count)
    valuePtr := make([]interface{}, count)

    for rows.Next() {
        for i, _ := range columns {
            valuePtr[i] = &values[i]
        }

        rows.Scan(valuePtr...)

        for i, col := range columns {
            var v interface{}

            val := values[i]

            b, ok := val.([]byte)
            if (ok) {
                v = string(b)
            } else {
                v = val
            }

            fmt.Println(col, v)
        }
    }
}
Undistinguished answered 6/10, 2018 at 15:44 Comment(1)
why fetch all rows when you need only 1? use SELECT * FROM tableName LIMIT 1; instead ;)Hydrated
I
2

Like this answer suggested, sqlx could be a good choice.

I personally use db.Unsafe() to ignore unwanted fields.

type MyTable struct {
    // list the fields you want here
    Name   string `db:"name"`
    Field1 string `db:"field1"`
}

db := try(sqlx.ConnectContext(context.Background(), "mysql",
    fmt.Sprintf("root:@tcp(%s:%d)/?charset=utf8mb4&timeout=3s", host, port)))
db = db.Unsafe()

rows := try(db.Queryx("select * from mytable"))
for rows.Next() {
    myTable := MyTable{}
    rows.StructScan(&myTable)
}
Incandesce answered 19/8, 2023 at 16:9 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.