Golang中database/sql包存在的代码缺陷问题

Golang中database/sql包存在的代码缺陷问题 go 版本:go 1.19

我的问题出在 database/sql 包上。服务中已有可用的 plsql 代码。值是通过 map 发送到服务的。但数量没有限制,

我需要通过 sql.Named 发送给 db.exec(),我尝试用循环和接口来检查,但都没有成功。

请帮帮我。

我的代码如下:

在控制器中

	const begin = `
		jsonData.Put('stateid', :stateid);
	`

       array_for_param := map[string]string{
		"stateid": "a",
	}

	temp, err := services.Perform(c, begin, array_for_param, i_User_Id)

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

服务代码:

	var params []interface{}

	for key, value := range array_for_param {
		params = append(params, sql.Named(key, value))
	}

	if _, err := db.Exec(declare+begin+end,
		sql.Named("i_User_Id", i_User_Id),
		params...,
	); err != nil {
		log.Fatal(err)
	}
	); err != nil {
		log.Fatal(err)
	}

我遇到的主要问题是,我需要使用一个 for 循环来发送 sql.Named 代码,而循环次数是未知的

	if _, err := db.Exec(declare+begin+end,
		sql.Named("i_User_Id", i_User_Id),
		for key, value := range array_for_param {
			return sql.Named(key, value)
		}
	); err != nil {
		log.Fatal(err)
	}

我也尝试过这样做


更多关于Golang中database/sql包存在的代码缺陷问题的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于Golang中database/sql包存在的代码缺陷问题的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


database/sql 包中,使用 sql.Named 参数时,需要将参数展开为切片。你的问题在于如何动态构建命名参数列表。以下是修正后的代码示例:

服务层代码修正:

func Perform(c context.Context, sqlStr string, params map[string]string, userID int) error {
    // 构建命名参数切片
    namedParams := make([]interface{}, 0, len(params)+1)
    
    // 添加固定参数
    namedParams = append(namedParams, sql.Named("i_User_Id", userID))
    
    // 动态添加map中的参数
    for key, value := range params {
        namedParams = append(namedParams, sql.Named(key, value))
    }
    
    // 执行SQL
    _, err := db.Exec(sqlStr, namedParams...)
    if err != nil {
        return err
    }
    
    return nil
}

控制器层调用示例:

const sqlStr = `
    DECLARE
        jsonData JSON_OBJECT_T := JSON_OBJECT_T();
    BEGIN
        jsonData.PUT('stateid', :stateid);
        -- 其他PL/SQL逻辑
    END;
`

params := map[string]string{
    "stateid": "a",
    "other_param": "value",  // 可以动态添加更多参数
}

err := services.Perform(c, sqlStr, params, userID)
if err != nil {
    log.Fatal(err)
}

关键点说明:

  1. namedParams 切片需要预分配容量以提高性能:make([]interface{}, 0, len(params)+1)
  2. 使用切片展开操作符 ... 传递参数:db.Exec(sqlStr, namedParams...)
  3. 可以混合固定参数和动态参数,顺序不影响,因为使用的是命名参数

更通用的解决方案(支持不同类型参数):

func PerformDynamic(c context.Context, sqlStr string, dynamicParams map[string]interface{}, fixedParams map[string]interface{}) error {
    namedParams := make([]interface{}, 0, len(dynamicParams)+len(fixedParams))
    
    // 添加固定参数
    for key, value := range fixedParams {
        namedParams = append(namedParams, sql.Named(key, value))
    }
    
    // 添加动态参数
    for key, value := range dynamicParams {
        namedParams = append(namedParams, sql.Named(key, value))
    }
    
    _, err := db.Exec(sqlStr, namedParams...)
    return err
}

这样处理可以支持任意数量的命名参数,且参数类型可以是 interface{} 以适应不同的数据类型需求。

回到顶部