Function in Go to execute select query on database and return json output

huangapple go评论87阅读模式
英文:

Function in Go to execute select query on database and return json output

问题

我正在使用Go编写一个函数来执行数据库上的select查询。

**输入:**字符串,例如"Select id, name, age from sometable"。这个查询每次都会改变。

**输出:**以JSON格式输出的select查询结果。

样例期望输出:{"Data":[{"id":1,"name":"abc", "age":40},{"id":2,"name":"xyz", "age":45}]}

样例实际输出:{"Data":[[1,"abc",40],[2,"xyz",45]]}

我只得到了值,而没有得到"column_name:value"的形式。我该如何得到期望的输出?

func executeSQL(queryStr string) []byte {
    connString := createConnectString()
    conn, err := sql.Open("mssql", connString)
    if err != nil {
        log.Fatal("Error while opening database connection:", err.Error())
    }
    defer conn.Close()

    rows, err := conn.Query(queryStr)
    if err != nil {
        log.Fatal("Query failed:", err.Error())
    }
    defer rows.Close()

    columns, _ := rows.Columns()
    count := len(columns)

    var v struct {
        Data []interface{} // `json:"data"`
    }

    for rows.Next() {
        values := make([]interface{}, count)
        valuePtrs := make([]interface{}, count)
        for i, _ := range columns {
            valuePtrs[i] = &values[i]
        }
        if err := rows.Scan(valuePtrs...); err != nil {
            log.Fatal(err)
        }
        v.Data = append(v.Data, values)
    }
    jsonMsg, err := json.Marshal(v)
    return jsonMsg
}
英文:

I am writing a function in Go to execute select query on database.

Input: String e.g. "Select id, name, age from sometable"
This query changes everytime.

Output: Output of select query in json format.

Sample Expected output: {"Data":[{"id":1,"name":"abc", "age":40},{"id":2,"name":"xyz", "age":45}]}

Sample Actual output: {"Data":[[1,"abc",40],[2,"xyz",45]]}

Instead of i.e. column_name:value, I get only values.
How do I get the expected output?

func executeSQL(queryStr string) []byte {
connString := createConnectString()
conn, err := sql.Open("mssql", connString)
if err != nil {
	log.Fatal("Error while opening database connection:", err.Error())
}
defer conn.Close()

rows, err := conn.Query(queryStr)
if err != nil {
	log.Fatal("Query failed:", err.Error())
}
defer rows.Close()

columns, _ := rows.Columns()
count := len(columns)

var v struct {
	Data []interface{} // `json:"data"`
}

for rows.Next() {
	values := make([]interface{}, count)
	valuePtrs := make([]interface{}, count)
	for i, _ := range columns {
		valuePtrs[i] = &values[i]
	}
	if err := rows.Scan(valuePtrs...); err != nil {
		log.Fatal(err)
	}
	v.Data = append(v.Data, values)
}
jsonMsg, err := json.Marshal(v)
return jsonMsg
}

答案1

得分: 1

我已经找到解决方案。这是我所做的:

func executeSQL(queryStr string) []byte {
    connString := createConnectString()
    conn, err := sql.Open("mssql", connString)
    if err != nil {
        log.Fatal("打开数据库连接时出错:", err.Error())
    }
    defer conn.Close()

    rows, err := conn.Query(queryStr)
    if err != nil {
        log.Fatal("查询失败:", err.Error())
    }
    defer rows.Close()

    columns, _ := rows.Columns()
    count := len(columns)

    var v struct {
        Data []interface{} // `json:"data"`
    }

    for rows.Next() {
        values := make([]interface{}, count)
        valuePtrs := make([]interface{}, count)
        for i, _ := range columns {
            valuePtrs[i] = &values[i]
        }
        if err := rows.Scan(valuePtrs...); err != nil {
            log.Fatal(err)
        }

        // 创建一个 map 来处理这个问题
        var m map[string]interface{}
        m = make(map[string]interface{})
        for i := range columns {
            m[columns[i]] = values[i]
        }
        v.Data = append(v.Data, m)
    }
    jsonMsg, err := json.Marshal(v)
    return jsonMsg
}

如果有更好的解决方案,请告诉我。

英文:

Got the solution. Here is what I did.

func executeSQL(queryStr string) []byte {
connString := createConnectString()
conn, err := sql.Open("mssql", connString)
if err != nil {
	log.Fatal("Error while opening database connection:", err.Error())
}
defer conn.Close()

rows, err := conn.Query(queryStr)
if err != nil {
	log.Fatal("Query failed:", err.Error())
}
defer rows.Close()

columns, _ := rows.Columns()
count := len(columns)

var v struct {
	Data []interface{} // `json:"data"`
}

for rows.Next() {
	values := make([]interface{}, count)
	valuePtrs := make([]interface{}, count)
	for i, _ := range columns {
		valuePtrs[i] = &values[i]
	}
	if err := rows.Scan(valuePtrs...); err != nil {
		log.Fatal(err)
	}
	
//Created a map to handle the issue
	var m map[string]interface{}
	m = make(map[string]interface{})
	for i := range columns {
		m[columns[i]] = values[i]
	}
	v.Data = append(v.Data, m)
}
jsonMsg, err := json.Marshal(v)
return jsonMsg
}

Let me know if there exists a better solution.

答案2

得分: 0

这段代码直接来自我的“沙盒”中的MsSQL(使用denisenkom/go-mssqldb和jmoiron/sqlx)-我认为它有助于展示不同的方法,也许QueryIntoMap是你正在寻找的:

package main

import (
	"log"
	"fmt"
	_ "github.com/denisenkom/go-mssqldb"
	"time"
	"github.com/jmoiron/sqlx"
	"encoding/json"
)

type Customer struct {
	CustomerId string `db:"customerID" json:"customer_id"`
	Company    interface{} `db:"companyName" json:"company_name"`
	Contact    interface{} `db:"contactName" json:"contact_name"`
}

func main() {
	connection := "server=192.168.55.3\\SqlExpress2012;database=Northwind;user id=me;Password=secret"

	//QueryIntoMap(connection)
	ScanIntoSlice(connection)
}

func QueryIntoMap(connection string) {

	fmt.Println("QueryIntoMap sample")
	fmt.Println("--------------------")

	sel := `select customerId, companyName, contactName
	from customers
	where customerId = :id`

	values := make(map[string]interface{})


	db, err := sqlx.Open("mssql", connection)
	//db.MapperFunc(strings.ToUpper)
	e(err)
	defer db.Close()
	tx := db.MustBegin()
	stmt, err := tx.PrepareNamed(sel)
	e(err)

	stmt.QueryRowx(map[string]interface{}{"id": "BONAP"}).MapScan(values)
	tx.Commit()

	for k, v := range values {
		fmt.Printf("%s %v\n", k, v)
	}

	js, err := json.Marshal(values)
	if err != nil {
		fmt.Println(err)
	}
	fmt.Println(string(js))
	fmt.Println("--------------------")
}

func ScanIntoStruct(connection string) {
	fmt.Println("Scan into struct sample")
	fmt.Println("--------------------")

	db, err := sqlx.Open("mssql", connection)
	e(err)
	defer db.Close()

	customer := Customer{}

	rows, err := db.Queryx(`select customerID, companyName, contactName
	from Customers`)

	for rows.Next() {
		err = rows.StructScan(&customer)
		if err != nil {
			log.Fatalln(err)
		}
		//fmt.Printf("%#v\n", user)
		fmt.Printf("%-10s %-50v %-50v\n",
			customer.CustomerId,
			customer.Company,
			customer.Contact)
		js, err := json.Marshal(customer)
		e(err)
		fmt.Println(string(js))
	}
	fmt.Println("--------------------")

}

func ScanIntoSlice(connection string) {
	fmt.Println("Scan into slice sample")
	fmt.Println("--------------------")
	start := time.Now()
	db, err := sqlx.Open("mssql", connection)
	e(err)
	defer db.Close()

	customers := []Customer{}

	err = db.Select(&customers, `select customerID, companyName, contactName from customers`)
	e(err)

	for i, customer := range customers {
		fmt.Printf("%3d. %-10s %-50v %-50v\n",
			i,
			customer.CustomerId,
			customer.Company,
			customer.Contact)
	}
	js, err := json.Marshal(customers)
	e(err)

	fmt.Println(string(js))

	fmt.Printf("%s", time.Since(start))
	fmt.Println("--------------------")

}

func e(err error) {
	if err != nil {
		log.Fatal(err)
	}
}

希望对你有帮助!

英文:

This code is directly from my "sandbox" for MsSQL (using denisenkom/go-mssqldb and jmoiron/sqlx) - I think it helps showing different approaches and probably QueryIntoMap is what you were looking for:

package main
import (
"log"
"fmt"
_ "github.com/denisenkom/go-mssqldb"
"time"
"github.com/jmoiron/sqlx"
"encoding/json"
)
type Customer struct {
CustomerId string `db:"customerID" json:"customer_id"`
Company    interface{} `db:"companyName" json:"company_name"`
Contact    interface{} `db:"contactName" json:"contact_name"`
}
func main() {
connection := "server=192.168.55.3\\SqlExpress2012;database=Northwind;user id=me;Password=secret"
//QueryIntoMap(connection)
ScanIntoSlice(connection)
}
func QueryIntoMap(connection string) {
fmt.Println("QueryIntoMap sample")
fmt.Println("--------------------")
sel := `select customerId, companyName, contactName
from customers
where customerId = :id`
values := make(map[string]interface{})
db, err := sqlx.Open("mssql", connection)
//db.MapperFunc(strings.ToUpper)
e(err)
defer db.Close()
tx := db.MustBegin()
stmt, err := tx.PrepareNamed(sel)
e(err)
stmt.QueryRowx(map[string]interface{}{"id": "BONAP"}).MapScan(values)
tx.Commit()
for k, v := range values {
fmt.Printf("%s %v\n", k, v)
}
js, err := json.Marshal(values)
if err != nil {
fmt.Println(err)
}
fmt.Println(string(js))
fmt.Println("--------------------")
}
func ScanIntoStruct(connection string) {
fmt.Println("Scan into struct sample")
fmt.Println("--------------------")
db, err := sqlx.Open("mssql", connection)
e(err)
defer db.Close()
customer := Customer{}
rows, err := db.Queryx(`select customerID, companyName, contactName
from Customers`)
for rows.Next() {
err = rows.StructScan(&customer)
if err != nil {
log.Fatalln(err)
}
//fmt.Printf("%#v\n", user)
fmt.Printf("%-10s %-50v %-50v\n",
customer.CustomerId,
customer.Company,
customer.Contact)
js, err := json.Marshal(customer)
e(err)
fmt.Println(string(js))
}
fmt.Println("--------------------")
}
func ScanIntoSlice(connection string) {
fmt.Println("Scan into slice sample")
fmt.Println("--------------------")
start := time.Now()
db, err := sqlx.Open("mssql", connection)
e(err)
defer db.Close()
customers := []Customer{}
err = db.Select(&customers, `select customerID, companyName, contactName from customers`)
e(err)
for i, customer := range customers {
fmt.Printf("%3d. %-10s %-50v %-50v\n",
i,
customer.CustomerId,
customer.Company,
customer.Contact)
}
js, err := json.Marshal(customers)
e(err)
fmt.Println(string(js))
fmt.Printf("%s", time.Since(start))
fmt.Println("--------------------")
}
func e(err error) {
if err != nil {
log.Fatal(err)
}
}

huangapple
  • 本文由 发表于 2017年4月12日 18:51:51
  • 转载请务必保留本文链接:https://go.coder-hub.com/43367505.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定