App Engine中的GoLang动态SQL查询

时间:2017-09-14 05:38:06

标签: mysql sql google-app-engine go dynamic

我想在GoLang中制作动态sql,我似乎找不到正确的方法来做到这一点。

基本上,我只想这样做:

query := "SELECT id, email, something FROM User"

var paramValues []string
filterString := ""

if userParams.Name != "" {
    paramString += " WHERE id = ?"
    paramValues = append(paramValues, userParams.Name)
}

if userParams.UserID != "" {
    if len(paramString) > 0 {
        paramString += " AND"
    } else {
        paramString += " WHERE"
    }

    paramString += " email = ?"
    paramValues = append(paramValues, userParams.UserID)
}
stmtOut, err := db.Prepare(query + paramString)

err = stmtOut.QueryRow(paramValues).Scan(&id, &email, &something)

building a dynamic query in mysql and golang

相关

我一直无法找到一种不允许sql注入的可靠方法。上述解决方案的问题是QueryRow()不会将[]字符串作为参数。

我想保护SQL注入,因此fmt.Sprintf并没有真正解决问题。

这样我就可以使用ID或Email对用户进行搜索,我也会将此逻辑用于具有更多可搜索字段的不同对象。

我正在使用go-sql-driver / mysql

1 个答案:

答案 0 :(得分:1)

这是我可以在我的本地机器上运行的东西(go1.8 linux / amd64和当前的GO MySQL驱动程序1.3)。

展示了几种方式。

package main

import (
    "database/sql"
    "log"

    _ "github.com/go-sql-driver/mysql"

    "fmt"
)

// var db *sql.DB
// var err error

/*
Database Name/Schema : Test123
Table Name: test
Table Columns and types:
number INT (PRIMARY KEY)
cube INT
*/

func main() {
    //Username root, password root
    db, err := sql.Open("mysql", "root:root@tcp(127.0.0.1:3306)/Test123?charset=utf8")

    if err != nil {
        fmt.Println(err) // needs proper handling as per app requirement
        return
    }
    defer db.Close()

    err = db.Ping()
    if err != nil {
        fmt.Println(err) // needs proper handling as per app requirement
        return
    }

    //Prepared statement for inserting data
    stmtIns, err := db.Prepare("INSERT INTO test VALUES( ?, ? )") // ? = placeholders
    if err != nil {
        panic(err.Error()) // needs proper handling as per app requirement
    }
    defer stmtIns.Close()

    //Insert cubes of 1- 10 numbers

    for i := 1; i < 10; i++ {
        _, err = stmtIns.Exec(i, (i * i * i)) // Insert tuples (i, i^3)
        if err != nil {
            panic(err.Error()) // proper error handling instead of panic in your app
        }
    }

    num := 3

    // Select statement

    dataEntity := "cube"
    condition := "WHERE number=? AND cube > ?"
    finalStatement := "SELECT " + dataEntity + " FROM test " + condition
    cubeLowerLimit := 10

    var myCube int
    err = db.QueryRow(finalStatement, num, cubeLowerLimit).Scan(&myCube)
    switch {
    case err == sql.ErrNoRows:
        log.Printf("No row with this number %d", num)
    case err != nil:
        log.Fatal(err)
    default:
        fmt.Printf("Cube for %d is %d\n", num, myCube)
    }

    var cubenum int

    // //Prepared statement for reading data
    stmtRead, err := db.Prepare(finalStatement)
    if err != nil {
        panic(err.Error()) // needs proper err handling
    }
    defer stmtRead.Close()

    // Query for cube of 5
    num = 5
    err = stmtRead.QueryRow(num, cubeLowerLimit).Scan(&cubenum)
    switch {
    case err == sql.ErrNoRows:
        log.Printf("No row with this number %d", num)
    case err != nil:
        log.Fatal(err)
    default:
        fmt.Printf("Cube number for %d is %d\n", num, cubenum)
    }

}

如果随后运行它,则需要删除数据库中的行,以便插入不会产生混乱(或者更改插入行代码以使其不会出现混乱)。我没有在Google App Engine上试过它。希望这会有所帮助。