Golang中如何更新Azure SQL Server的变量

Golang中如何更新Azure SQL Server的变量 我是Go语言的新手,正在树莓派(Linux开发板)上开发蓝牙低功耗信标接收器。已经实现了从信标接收数据的功能,现在需要将数据上传到Azure SQL服务器,但我无法将接收到的变量插入到SQL语句中。我在此发布我的代码(Azure示例中的SQL代码),请指导如何插入变量…如recvid、recvtype、b.uuid、rssi等。

package main

import (
"fmt"
"log"
"context"
"strconv"

"github.com/paypal/gatt"
"github.com/paypal/gatt/examples/option"
    _ "github.com/denisenkom/go-mssqldb"
    "database/sql"
)
var db *sql.DB

var recvid string = "D1"     // 需要插入到SQL中
var recvtype string ="SLAVE"   // 需要插入到SQL中

func onPeripheralDiscovered(periphera gatt.Peripheral, advretisement *gatt.Advertisement, rssi int) {
b, err := NewiBeacon(advretisement.ManufacturerData)
if err == nil {
fmt.Println("UUID: ", b.uuid)  // 需要插入到SQL中
fmt.Println("Major: ", b.major)
fmt.Println("Minor: ", b.minor)
fmt.Println("RSSI: ", rssi)  // 需要插入到SQL中

          rssival := strconv.Itoa(rssi)

          fmt.Println("----RSSI STING: ", rssival)  

insertvalues()

}}
func insertvalues(){
ctx := context.Background()

result, err := db.ExecContext(ctx,"INSERT INTO LOCATION_PAYLOAD (RSSI) VALUES (rssival)")    // 无法正常工作

if err != nil {
log.Fatal("Error creating connection pool: ", err.Error())
}
fmt.Println("RESULT",result)
}
func main() {

    // 构建连接字符串
connString := fmt.Sprintf("server=%s;user id=%s;password=%s;port=%d;database=%s;",
    server, user, password, port, database)

var err error

// 创建连接池
db, err = sql.Open("sqlserver", connString)
if err != nil {
    log.Fatal("Error creating connection pool: ", err.Error())
}
ctx := context.Background()
err = db.PingContext(ctx)
if err != nil {
    log.Fatal(err.Error())
}
fmt.Printf("Connected!\n")
}

更多关于Golang中如何更新Azure SQL Server的变量的实战教程也可以访问 https://www.itying.com/category-94-b0.html

6 回复

Ksundeep:

VALUES (rssival)”

请将完整的示例代码放入代码框中以提高可读性,并尝试以下写法:

VALUES(?)", rssival)

在某些服务器上也可能需要使用 ([RSSI]) 而不是 (RSSI)。您之前是否在某个 MSSQL 客户端(如 VSCode、SSMS 等)中测试过您的命令?

更多关于Golang中如何更新Azure SQL Server的变量的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


在驱动页面:https://github.com/denisenkom/go-mssqldb#parameters 中这样说明:

参数

sqlserver 驱动程序使用标准的 MS SQL Server 语法,并期望 SQL 查询中的参数采用 @Name@p1@pN(按位置顺序)的形式。

db.QueryContext(ctx, `select * from t where ID = @ID and Name = @p2;`, sql.Named("ID", 6), "Bob")

因此你的代码应该是:

result, err := db.ExecContext(ctx,"INSERT INTO LOCATION_PAYLOAD (RSSI) VALUES (@p1)", rssival)
_, err := db.Exec("INSERT INTO location_payload ([RSSI]) VALUES(?)", rssival)
if err != nil {
   log.Print(err.Error())
}

基本上这应该能正常工作。我在现有的项目中使用的就是这种语法,当然我把你的变量放入了。?很重要,因为它会将参数中的变量值放入查询中。我使用的是Exec而不是ExecContext。

不过,最好先在普通电脑上测试这些命令是否真的能与你的服务器配合工作,然后再用Go编写命令代码,因为很可能存在除语法错误之外的其他问题。还要确保表中字段的类型与你程序中要插入的变量类型一致。

补充说明:我不是mssql专家,无法确定服务器版本或其他特定的服务器设置在这里是否重要。

Ksundeep:

sql.Open(“sqlserver”, connString)

看来这就是问题所在…

https://github.com/denisenkom/go-mssqldb#query-parameter-token-replace-driver-mssql

查询参数标记替换(驱动 “mssql”)

如果使用驱动名称 “mssql”(而非 “sqlserver”),SQL 文本将被宽松解析,并尝试使用以下任一标识符进行提取:

  • ?
  • ?nnn
  • :nnn
  • $nnn

不建议在 SQL Server 中使用此方式。查询解析至少存在一个现有的 无法修复 问题。

请使用原生 “@Name” 参数,并配合 “sqlserver” 驱动名称。

我想我使用了过时的语法… :roll_eyes:

由于Linux板仅支持在终端上工作,因此未在任何IDE上尝试。上述使用"?"的建议并不奏效。恳请提供准备插入语句的方法或支持链接。不需要特定的上下文,任何预处理方法或函数类型也能解决我的问题。

谢谢。

以下是完整代码:

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

var db *sql.DB
var recvid string = “D1”  -- VALUE TO BE INSERTED -- 
var recvtype string =“SLAVE” -- VALUE TO BE INSERTED -- 


func onPeripheralDiscovered(periphera gatt.Peripheral, advretisement *gatt.Advertisement, rssi int) {
	b, err := NewiBeacon(advretisement.ManufacturerData)
	if err == nil {
		fmt.Println("UUID: ", b.uuid)    -- VALUE TO BE INSERTED -- 
		fmt.Println("Major: ", b.major)  -- VALUE TO BE INSERTED -- 
		fmt.Println("Minor: ", b.minor)  -- VALUE TO BE INSERTED -- 
		fmt.Println("RSSI: ", rssi)     -- VALUE TO BE INSERTED -- 
              
              rssival := strconv.Itoa(rssi)
              fmt.Println("----RSSI STING: ", rssival)  

  ctx := context.Background()
  result, err := db.ExecContext(ctx,"INSERT INTO LOCATION_PAYLOAD (RSSI) VALUES (rssival)")
  if err != nil {
    log.Fatal("Error creating connection pool: ", err.Error())
    }
  fmt.Println("RESULT",result)
 
}}


func main() {

        // Build connection string
    connString := fmt.Sprintf("server=%s;user id=%s;password=%s;port=%d;database=%s;",
        server, user, password, port, database)

    var err error

    // Create connection pool
    db, err = sql.Open("sqlserver", connString)
    if err != nil {
        log.Fatal("Error creating connection pool: ", err.Error())
    }
    ctx := context.Background()
    err = db.PingContext(ctx)
    if err != nil {
        log.Fatal(err.Error())
    }
    fmt.Printf("Connected!\n")
     
}

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

在Go语言中,你需要使用参数化查询来安全地将变量插入到SQL语句中。直接拼接字符串容易导致SQL注入漏洞,并且在你当前的代码中,变量rssival在SQL字符串中未被正确引用。以下是修改后的insertvalues函数,展示如何使用参数化查询插入变量:

func insertvalues(b iBeacon, rssi int) {
    ctx := context.Background()
    
    // 使用参数化查询,? 是占位符(具体占位符可能因驱动而异,go-mssqldb 使用 @p1, @p2 等)
    query := `INSERT INTO LOCATION_PAYLOAD (recvid, recvtype, uuid, rssi) VALUES (@p1, @p2, @p3, @p4)`
    
    result, err := db.ExecContext(ctx, query,
        sql.Named("p1", recvid),      // 全局变量 recvid
        sql.Named("p2", recvtype),    // 全局变量 recvtype
        sql.Named("p3", b.uuid),      // iBeacon 的 UUID
        sql.Named("p4", rssi))        // RSSI 值(整数类型,无需转换为字符串)
    
    if err != nil {
        log.Fatal("Error inserting data: ", err.Error())
    }
    rowsAffected, _ := result.RowsAffected()
    fmt.Printf("Rows affected: %d\n", rowsAffected)
}

同时,你需要修改onPeripheralDiscovered函数来传递必要的参数:

func onPeripheralDiscovered(peripheral gatt.Peripheral, advertisement *gatt.Advertisement, rssi int) {
    b, err := NewiBeacon(advertisement.ManufacturerData)
    if err == nil {
        fmt.Println("UUID: ", b.uuid)
        fmt.Println("Major: ", b.major)
        fmt.Println("Minor: ", b.minor)
        fmt.Println("RSSI: ", rssi)
        
        // 调用插入函数,传递 iBeacon 实例和 RSSI
        insertvalues(b, rssi)
    }
}

确保你的数据库表LOCATION_PAYLOAD包含与插入值匹配的列(例如recvidrecvtypeuuidrssi)。参数化查询通过sql.Named函数或直接使用位置参数(如@p1)来绑定变量,这避免了SQL注入风险并正确处理数据类型。在go-mssqldb驱动中,占位符通常使用@p1@p2等形式。如果你的驱动版本不同,请参考其文档调整占位符语法(例如,某些配置可能使用?)。

回到顶部