2014-02-17 5 views
3

У меня есть таблица t, содержащая множество столбцов, и мой sql выглядит так: select * from t. Теперь я хочу только сканировать один или два столбца из набора расширенных строк. Тем не менее, sql.Scan принимает dest ...interface{} в качестве аргументов. Означает ли это, что я должен проверять все и использовать только тот столбец, который мне нужен?sql: scan row (s) с неизвестным количеством столбцов (выберите * from ...)

Я знаю, что могу изменить sql от select * до select my_favorite_rows, однако в этом случае у меня нет возможности изменить sql.

Спасибо, Elgs

+2

Он возвращает ссылку sql.Rows. Используйте rows.Next для повторения, пока вы не найдете нужную строку. http://go-database-sql.org/retrieving.html – elithrar

+0

Спасибо @elithrar. Мне жаль, что я не дал понять. Мой вопрос в том, что я хочу только один столбец или два из большого количества столбцов. Есть ли удобный способ сделать это? Либо от имени столбца, либо от имени столбца? –

+1

Я не думаю, что есть удобный способ сделать это с помощью пакета sql. Возможно, посмотрите на jmoiron/sqlx для некоторых расширений sql, которые включают в себя то, что вы пытаетесь сделать. В противном случае sql.Rows предоставляет функцию Columns(), которую вы можете использовать, чтобы идентифицировать cols, который вы хотите. – Alex

ответ

13

Вы можете использовать Rows.Columns, например,

package main 

import (
    "database/sql" 
    "fmt" 

    "github.com/lib/pq" 
) 

type Vehicle struct { 
    Id  int 
    Name string 
    Wheels int 
} 

// VehicleCol returns a reference for a column of a Vehicle 
func VehicleCol(colname string, vh *Vehicle) interface{} { 
    switch colname { 
    case "id": 
     return &vh.Id 
    case "name": 
     return &vh.Name 
    case "wheels": 
     return &vh.Wheels 
    default: 
     panic("unknown column " + colname) 
    } 
} 

func panicOnErr(err error) { 
    if err != nil { 
     panic(err.Error()) 
    } 
} 

func main() { 
    conn, err := pq.ParseURL(`postgres://docker:[email protected]:5432/pgsqltest?schema=public`) 
    panicOnErr(err) 

    var db *sql.DB 
    db, err = sql.Open("postgres", conn) 
    panicOnErr(err) 

    var rows *sql.Rows 
    rows, err = db.Query("select * from vehicle") 
    panicOnErr(err) 

    // get the column names from the query 
    var columns []string 
    columns, err = rows.Columns() 
    panicOnErr(err) 

    colNum := len(columns) 

    all := []Vehicle{} 

    for rows.Next() { 
     vh := Vehicle{} 

     // make references for the cols with the aid of VehicleCol 
     cols := make([]interface{}, colNum) 
     for i := 0; i < colNum; i++ { 
      cols[i] = VehicleCol(columns[i], &vh) 
     } 

     err = rows.Scan(cols...) 
     panicOnErr(err) 

     all = append(all, vh) 
    } 

    fmt.Printf("%#v\n", all) 
} 
+1

Благодарим вас за код @metakeule. Я думаю, что это может быть отправной точкой для дальнейшего переноса этих низкоуровневых apis, чтобы сделать доступ к базе данных Go более доступной. Go's sql api выглядит очень уродливо. –

+4

@ElgsQianChen да, это означало как отправную точку и лучше понять sql api. пожалуйста, подумайте о принятии ответа или голосовании за него. – metakeule

+1

Спасибо @metakeule, ваш код помогает. –

Смежные вопросы