Golang与MSSQL数据库操作实践指南

Golang与MSSQL数据库操作实践指南 您好,

我的英语不是很好,所以请原谅我的错误。 我很多很多年前曾经是一名开发人员。 现在我又重新拾起,正在学习 Go 语言和 MS SQL。

我想做一件相当简单的事情,但不知为何,尽管在谷歌上进行了大量搜索,却找不到正确的解决方案。 这是我的目标。 我希望通过 Go 语言访问我的 MS 数据库并执行一个 SELECT 语句。这个语句应该从 ID 1 开始,然后循环执行直到结束。

我认为我在处理语句时犯了错误。

以下是代码:

package main

import (
    "database/sql"
    "flag"
    "fmt"
    "log"

    _ "github.com/denisenkom/go-mssqldb"
)

var (
    debug         = flag.Bool("debug", false, "enable debugging")
    password      = flag.String("password", "", "the database password")
    port     *int = flag.Int("port", 1433, "the database port")
    server        = flag.String("server", "", "the database server")
    user          = flag.String("user", "", "the database user")
)

func main() {

    flag.Parse()

    if *debug {
        fmt.Printf(" password:%s\n", *password)
        fmt.Printf(" port:%d\n", *port)
        fmt.Printf(" server:%s\n", *server)
        fmt.Printf(" user:%s\n", *user)
    }

    connString := fmt.Sprintf("server=%s;user id=%s;password=%s;port=%d", *server, *user, *password, *port)
    if *debug {
        fmt.Printf(" connString:%s\n", connString)
    }
    conn, err := sql.Open("mssql", connString)
    if err != nil {
        log.Fatal("Open connection failed:", err.Error())
    }
    defer conn.Close()

    idi := 1
    stmt, err := conn.Prepare("select test from test.dbo.test where id =", idi)
    if err != nil {
        log.Fatal("Prepare failed:", err.Error())
    }
    defer stmt.Close()

}

错误信息: \test.go:42:27: too many arguments in call to conn.Prepare have (string, int) want (string)

你们有什么想法吗?

此致 Rene


更多关于Golang与MSSQL数据库操作实践指南的实战教程也可以访问 https://www.itying.com/category-94-b0.html

2 回复

Rene,请查阅文档(https://golang.org/pkg/database/sql/#DB.Prepare)。Prepare 方法只需要一个参数。步骤是:1) 准备你想要执行的 SQL 字符串 2) 使用 Execute/Query/QueryRow 方法执行它。

可能类似于这样:

stmt, err := conn.Prepare("select test from test.dbo.test where id = @id")
if err != nil {
	log.Fatal("Prepare failed:", err.Error())
}
defer stmt.Close()

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

....

更多关于Golang与MSSQL数据库操作实践指南的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


在Go语言中,Prepare方法只接受一个字符串参数(SQL语句),不能直接传递参数。参数绑定需要在执行查询时通过QueryExec方法完成。以下是修正后的代码:

package main

import (
    "database/sql"
    "flag"
    "fmt"
    "log"

    _ "github.com/denisenkom/go-mssqldb"
)

var (
    debug    = flag.Bool("debug", false, "enable debugging")
    password = flag.String("password", "", "the database password")
    port     = flag.Int("port", 1433, "the database port")
    server   = flag.String("server", "", "the database server")
    user     = flag.String("user", "", "the database user")
)

func main() {
    flag.Parse()

    if *debug {
        fmt.Printf(" password:%s\n", *password)
        fmt.Printf(" port:%d\n", *port)
        fmt.Printf(" server:%s\n", *server)
        fmt.Printf(" user:%s\n", *user)
    }

    connString := fmt.Sprintf("server=%s;user id=%s;password=%s;port=%d", 
        *server, *user, *password, *port)
    
    if *debug {
        fmt.Printf(" connString:%s\n", connString)
    }
    
    db, err := sql.Open("mssql", connString)
    if err != nil {
        log.Fatal("Open connection failed:", err.Error())
    }
    defer db.Close()

    // 验证数据库连接
    err = db.Ping()
    if err != nil {
        log.Fatal("Database connection failed:", err.Error())
    }

    // 准备SQL语句(使用参数占位符)
    stmt, err := db.Prepare("SELECT test FROM test.dbo.test WHERE id = @p1")
    if err != nil {
        log.Fatal("Prepare failed:", err.Error())
    }
    defer stmt.Close()

    // 循环查询示例
    for id := 1; ; id++ {
        var testValue string
        
        // 执行查询并绑定参数
        err := stmt.QueryRow(sql.Named("p1", id)).Scan(&testValue)
        if err != nil {
            if err == sql.ErrNoRows {
                fmt.Printf("ID %d: 没有找到记录\n", id)
                break // 或者继续循环
            }
            log.Printf("查询ID %d失败: %v\n", id, err)
            break
        }
        
        fmt.Printf("ID %d: %s\n", id, testValue)
    }
}

或者使用更简洁的方式,不使用Prepare:

// 直接查询的替代方案
for id := 1; ; id++ {
    var testValue string
    
    err := db.QueryRow("SELECT test FROM test.dbo.test WHERE id = @p1", 
        sql.Named("p1", id)).Scan(&testValue)
    
    if err != nil {
        if err == sql.ErrNoRows {
            fmt.Println("查询结束")
            break
        }
        log.Fatal("Query failed:", err.Error())
    }
    
    fmt.Printf("ID %d: %s\n", id, testValue)
}

如果需要处理可能不连续的ID,可以这样查询所有记录:

// 查询所有记录
rows, err := db.Query("SELECT id, test FROM test.dbo.test ORDER BY id")
if err != nil {
    log.Fatal("Query failed:", err.Error())
}
defer rows.Close()

for rows.Next() {
    var id int
    var testValue string
    
    err := rows.Scan(&id, &testValue)
    if err != nil {
        log.Fatal("Scan failed:", err.Error())
    }
    
    fmt.Printf("ID %d: %s\n", id, testValue)
}

if err = rows.Err(); err != nil {
    log.Fatal("Rows error:", err.Error())
}

关键点:

  1. Prepare方法只接受SQL字符串,不能包含参数
  2. 参数通过@p1@p2等占位符表示
  3. 使用sql.Named()或直接传递参数值来绑定参数
  4. 使用QueryRow获取单行结果,Query获取多行结果
  5. 使用Scan将结果映射到变量
回到顶部