在Golang中执行SQL查询

时间:2018-03-16 13:07:36

标签: database go prepared-statement

我见过两种人使用Golang内置database/sql查询执行查询的方法。其中一个是使用fmt.Sprintf

func (db *DB) CreateUserTable() (sql.Result, error) {
    statement := "CREATE TABLE %s (%s, %s, %s, %s, %s)"
    v := []interface{}{"User", "ID int PRIMARY KEY NOT NULL", "Name varchar(100) UNIQUE", "Email varchar(100) UNIQUE", "Address varchar(100) ",  "Username varchar(100) UNIQUE"}
    return db.Exec(fmt.Sprintf(statement, v...))
}

另一个正在使用预备声明:

func (db *DB) CreateUserTable() (sql.Result, error) {    
    statement, err := db.Prepare("INSERT INTO User(tbl1,tbl2,tbl3) VALUES(?,?,?)")
    if err != nil {
        log.Fatal(err)
    }
    return statement.Exec("value1", "value2", "value3")
}

第一个使您能够动态设置表名,列名和值,从而获益。但第二个只针对价值观。有什么不同?我应该使用哪一个?

2 个答案:

答案 0 :(得分:3)

从不从来自系统外部的字符串构建SQL。

enter image description here

始终使用nil语法。

如果必须设置SQL部分(如表名),请准备多个包含值?的完整SQL语句。选择要执行的SQL,可能基于用户输入,但从不从用户输入构建SQL

答案 1 :(得分:1)

使用预准备语句更加清晰,这样每当需求发生变化时,您都可以轻松修改语句。还要防止SQL注入。

  

准备好的语句比连接字符串要好得多   通常的原因(例如,避免SQL注入攻击)。

     

在MySQL中,参数占位符是?,而在PostgreSQL中它是$ N,   其中N是数字。 SQLite接受其中任何一个。

还有一件事是Prepared语句可以用于重复方法,可以多次执行并且可以被销毁。

stmt, err := db.Prepare("select id, name from users where id = ?")
if err != nil {
    log.Fatal(err)
}
defer stmt.Close() // closing the statement
rows, err := stmt.Query(1)

你正在使用接口

func (db *DB) CreateUserTable() (sql.Result, error) {
    statement := "CREATE TABLE %s (%s, %s, %s, %s, %s)"
    v := []interface{}{"User", "ID int PRIMARY KEY NOT NULL", "Name varchar(100) UNIQUE", "Email varchar(100) UNIQUE", "Address varchar(100) ",  "Username varchar(100) UNIQUE"}
    return db.Exec(fmt.Sprintf(statement, v...))
}

可以采取任何类型的参数,可能是易受攻击的

有关详细信息,请转到Link