英文:
Dynamically passing SQL parameters in Golang
问题
我可以帮你翻译这段内容。以下是翻译结果:
我在数据库表中有一个如下的SELECT查询语句。
select * from dbo.student where dob > @date_of_birth and grade = @grade
我将从Kafka消息中获取参数和值,如下所示,并且需要在Golang中用这个Kafka消息的值替换这两个参数。数据库表中的表名和参数可能对于每个查询都不同。因此,我需要编写一个通用函数来替换参数,无论是哪个表或者需要传递多少个参数。
{
"message": [{
"sql_table": "student",
"input_params": [{
"key": "@date_of_birth",
"value": "2012-03-03"
},
{
"key": "@grade",
"value": "5"
}
]
}]
}
英文:
I have a SELECT query like below in the database table as constant.
select * from dbo.student where dob > @date_of_birth and grade = @grade
I will be getting the parameters and values from a Kafka message for like below and I needs to replace the two parameters with this Kafka message value in Golang. This table and parameters can be different for each query in the database table. So i need to write a generic function to replace the params if any table or any number parameters to be passed.
{
"message": [{
"sql_table": "student",
"input_params": [{
"key": "@date_of_birth",
"value": "2012-03-03"
},
{
"key": "@grade",
"value": "5"
}
]
}
]
}
答案1
得分: 1
首先,你需要确保你正在使用的数据库驱动程序支持命名参数(例如,go-mssqldb),然后可以按照以下步骤进行操作:
将 Kafka 消息解组为一个结构体,循环遍历输入参数以创建参数列表(类型为 []any)。在循环体中,使用每个输入参数对象创建一个 sql.NamedArg 值,然后在调用 db.Query() 方法时使用 ... 来“解包”参数。
type KafkaMessage struct {
Message []Message `json:"message"`
}
type Message struct {
SQLTable string `json:"sql_table"`
InputParams []InputParams `json:"input_params"`
}
type InputParams struct {
Key string `json:"key"`
Value any `json:"value"`
}
func ExecQuery(db *sql.DB, m Message) (*sql.Rows, error) {
queryString := "..." // 根据 m.SQLTable 获取正确的 SQL 查询字符串
args := make([]any, len(m.InputParams))
for i, pp := range m.InputParams {
name := pp.Key[1:] // 去掉开头的 "@"
args[i] = sql.Named(name, pp.Value)
}
return db.Query(queryString, args...)
}
// ...
var km KafkaMessage // 将 Kafka 消息解组为 km
rows, err := ExecQuery(db, km.Message[0])
if err != nil {
panic(err)
}
defer rows.Close()
for rows.Next() {
// ...
}
英文:
First you need to make sure the db driver that you're using does have support for named parameters (go-mssqldb does, for example), then you can do the following:
Unmarshal the kafka message into a struct, loop over the input params to create a list of args (of type []any), in the loop's body use each input params object to create an sql.NamedArg value, then use ... to "unpack" the args when calling the db.Query() method.
type KafkaMessage struct {
Message []Message `json:"message"`
}
type Message struct {
SQLTable string `json:"sql_table"`
InputParams []InputParams `json:"input_params"`
}
type InputParams struct {
Key string `json:"key"`
Value any `json:"value"`
}
func ExecQuery(db *sql.DB, m Message) (*sql.Rows, error) {
queryString := "..." // based on m.SQLTable get the correct SQL query string
args := make([]any, len(m.InputParams))
for i, pp := range m.InputParams {
name := pp.Key[1:] // drop the leading "@"
args[i] = sql.Named(name, pp.Value)
}
return db.Query(queryString, args...)
}
// ...
var km KafkaMessage // unmarshal the kafka message into km
rows, err := ExecQuery(db, km.Message[0])
if err != nil {
panic(err)
}
defer rows.Close()
for rows.Next() {
// ...
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论