2017-09-14 17 views
0

GoLangで動的SQLを作成したいのですが、正しい方法を見つけることができないようです。GoLang App Engineの動的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または電子メールのいずれかを使用してユーザーの検索を許可することができます。さらに、このロジックを検索可能なフィールドの異なるオブジェクトに使用します。

私は行く-SQL-ドライバ/ mysqlの

答えて

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:[email protected](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で試してみませんでした。お役に立てれば。