You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Golang中编写通用函数动态替换SQL参数

Golang 通用SQL参数替换实现

需求说明

数据库中存储着带@前缀参数占位符的SELECT语句,示例如下:

select * from dbo.student where dob > @date_of_birth and grade = @grade

从Kafka获取的参数JSON格式(已翻译为中文):

{
    "message": [{
        "sql_table": "student",
        "input_params": [{
                "key": "@date_of_birth",
                "value": "2012-03-03"
            },
            {
                "key": "@grade",
                "value": "5"
            }
        ]
    }
  ]
}

需要实现一个通用函数,支持任意表、任意数量参数的占位符替换。


实现代码

1. 定义JSON解析结构体

先定义对应Kafka消息格式的结构体,方便解析参数:

type Param struct {
    Key   string `json:"key"`
    Value string `json:"value"`
}

type KafkaMessageItem struct {
    SqlTable    string `json:"sql_table"`
    InputParams []Param `json:"input_params"`
}

type KafkaMessage struct {
    Message []KafkaMessageItem `json:"message"`
}

2. 通用参数替换函数

实现核心替换逻辑,同时处理字符串参数的单引号转义、数字参数的格式适配:

import (
    "strings"
)

// ReplaceSQLParams 接收原始SQL和参数列表,返回替换后的SQL语句
func ReplaceSQLParams(originalSQL string, params []Param) string {
    replacedSQL := originalSQL
    for _, p := range params {
        var valueStr string
        // 判断参数是否为数字,数字类型直接使用原值,字符串类型添加单引号并转义内部单引号
        if isNumeric(p.Value) {
            valueStr = p.Value
        } else {
            escapedValue := strings.ReplaceAll(p.Value, "'", "''")
            valueStr = "'" + escapedValue + "'"
        }
        replacedSQL = strings.ReplaceAll(replacedSQL, p.Key, valueStr)
    }
    return replacedSQL
}

// isNumeric 判断字符串是否为纯数字
func isNumeric(s string) bool {
    for _, c := range s {
        if c < '0' || c > '9' {
            return false
        }
    }
    return true
}

3. 使用示例

模拟从Kafka获取消息、解析并完成参数替换的完整流程:

import (
    "encoding/json"
    "fmt"
)

func main() {
    // 模拟从数据库读取的原始SQL
    originalSQL := "select * from dbo.student where dob > @date_of_birth and grade = @grade"

    // 模拟Kafka获取的JSON字符串
    kafkaJSON := `{
        "message": [{
            "sql_table": "student",
            "input_params": [{
                    "key": "@date_of_birth",
                    "value": "2012-03-03"
                },
                {
                    "key": "@grade",
                    "value": "5"
                }
            ]
        }
      ]
    }`

    // 解析Kafka消息
    var msg KafkaMessage
    err := json.Unmarshal([]byte(kafkaJSON), &msg)
    if err != nil {
        fmt.Printf("JSON解析失败: %v\n", err)
        return
    }

    // 处理消息(此处取第一个消息项,实际场景可根据需求遍历所有message元素)
    if len(msg.Message) == 0 {
        fmt.Println("无可用消息数据")
        return
    }
    item := msg.Message[0]

    // 执行参数替换
    finalSQL := ReplaceSQLParams(originalSQL, item.InputParams)
    fmt.Println("替换后的SQL:", finalSQL)
}

注意事项

  • 上述实现仅做基础的格式处理和注入防护,生产环境优先推荐使用数据库驱动的参数化查询(如database/sql包的Prepare+Query/Exec),从根源避免SQL注入风险。
  • 若占位符格式不是@前缀,只需调整替换逻辑中的占位符匹配规则即可,函数本身具备通用性。
  • 多表场景下,可维护一个表名到原始SQL的映射关系,根据sql_table字段匹配对应的SQL语句。

内容的提问来源于stack exchange,提问作者John Scott

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 01:12:37