Golang中如何在查询语句中使用SQL变量

Golang中如何在查询语句中使用SQL变量 你好,

我尝试在查询中使用SQL变量,但MySQL返回错误信息,提示我编写的SQL语句有误。

是否可以像下面这样操作?:

q := `SET @x=1; 
      SELECT id, @x+1 FROM my_table;
   `
rows, err := db.Query(q)

我阅读了:https://golang.org/pkg/database/sql/#DB.Query

2 回复

更多关于Golang中如何在查询语句中使用SQL变量的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


在Go的database/sql包中,Query()方法不支持在一次调用中执行多条SQL语句。你提供的代码会触发MySQL的语法错误,因为MySQL驱动默认禁止多语句执行。

正确的实现方式

方法1:分步执行(推荐)

// 设置变量
_, err := db.Exec("SET @x = ?", 1)
if err != nil {
    log.Fatal(err)
}

// 使用变量查询
rows, err := db.Query("SELECT id, @x+1 FROM my_table")
if err != nil {
    log.Fatal(err)
}
defer rows.Close()

for rows.Next() {
    var id int
    var result int
    if err := rows.Scan(&id, &result); err != nil {
        log.Fatal(err)
    }
    fmt.Println(id, result)
}

方法2:使用会话变量(单条语句)

// 在单条查询中设置和使用变量
q := `SELECT id, (@x := 1) + 1 FROM my_table`
rows, err := db.Query(q)
if err != nil {
    log.Fatal(err)
}
defer rows.Close()

方法3:启用多语句执行(不推荐,有安全风险)

// 在DSN中添加参数
dsn := "user:password@tcp(127.0.0.1:3306)/dbname?multiStatements=true"
db, err := sql.Open("mysql", dsn)

// 然后可以执行多语句
q := `SET @x=1; SELECT id, @x+1 FROM my_table;`
rows, err := db.Query(q)

使用预处理语句的示例

// 使用预处理语句和变量
stmt, err := db.Prepare("SELECT id, ?+1 FROM my_table")
if err != nil {
    log.Fatal(err)
}
defer stmt.Close()

rows, err := stmt.Query(1) // 这里的1会替换?
if err != nil {
    log.Fatal(err)
}
defer rows.Close()

事务中的使用

tx, err := db.Begin()
if err != nil {
    log.Fatal(err)
}
defer tx.Rollback()

// 在事务中设置变量
_, err = tx.Exec("SET @x = ?", 1)
if err != nil {
    log.Fatal(err)
}

// 使用变量查询
rows, err := tx.Query("SELECT id, @x+1 FROM my_table")
if err != nil {
    log.Fatal(err)
}
defer rows.Close()

err = tx.Commit()
if err != nil {
    log.Fatal(err)
}

分步执行是最安全且符合Go标准库设计的方式。database/sql包的设计原则是每次查询只执行一条SQL语句,这有助于防止SQL注入攻击并保持代码的清晰性。

回到顶部