showliuzp 2025-10-16 10:50 采纳率: 84.3%
浏览 3
已结题

golang gorm拼装sql


err = DbSlave.Raw("Select count(*) as chat_count from(select distinct(to_uid) from lu_live_report where uid=? and create_at >=? and create_at <= ? and (video_unix != 0 or voice_unix !=0) group by to_uid) as a",streamer_id,start_unixtime,end_unixtime).Scan(&total).Error
    return
}



我有如上的sql,要根据start_unixtime,end_unixtime是否有值进行拼装,但现在的是写死,不支持动态的。应该做拼
我试图拼装了以下的,但不好使
    sql := "Select count(*) as chat_count from(select distinct(to_uid) from lu_live_report where uid=?"

    if start_unixtime != 0&& end_unixtime != 0{
        sql += " and create_at >= ? and create_at <= ?"
    }

    sql += " and (video_unix != 0 or voice_unix !=0) group by to_uid) as a"
    err = DbSlave.Raw(sql,streamer_id,start_unixtime,end_unixtime).Scan(&total).Error

  • 写回答

5条回答 默认 最新

  • 檀越@新空间 2025-10-16 11:01
    关注

    上午好☀️☀️☀️️
    本答案参考通义千问

    你目前的SQL拼接逻辑存在几个问题,最核心的问题是:在动态拼接SQL时,参数绑定(?)的数量和顺序必须与实际传入的参数一一对应。你当前的写法中,当 start_unixtimeend_unixtime 不为 0 时,会添加两个 ?,但你只传了三个参数(streamer_id, start_unixtime, end_unixtime),这会导致 GORM 报错。


    ✅ 正确的处理方式如下:

    1. 根据条件动态构建 SQL 语句,并正确管理参数

    var sql string
    var args []interface{}
    
    sql = "SELECT count(*) as chat_count FROM (SELECT DISTINCT(to_uid) FROM lu_live_report WHERE uid=?"
    
    args = append(args, streamer_id)
    
    if start_unixtime != 0 && end_unixtime != 0 {
        sql += " AND create_at >= ? AND create_at <= ?"
        args = append(args, start_unixtime, end_unixtime)
    }
    
    sql += " AND (video_unix != 0 OR voice_unix != 0) GROUP BY to_uid) AS a"
    
    err := DbSlave.Raw(sql, args...).Scan(&total).Error
    return err
    

    🔍 说明:

    • sql 是动态构建的 SQL 字符串。
    • args 是一个切片,用于存储所有需要绑定的参数。
    • 使用 args... 将切片展开为多个参数传递给 Raw() 方法。
    • 这样可以确保参数数量与 SQL 中的 ? 数量一致,避免 GORM 报错。

    🧠 注意事项:

    • 不要使用字符串拼接来构造 SQL 查询,尤其是涉及用户输入的部分,容易造成 SQL 注入攻击。GORM 的 Raw() 方法支持参数绑定,应优先使用这种方式。
    • 如果你还需要处理 start_unixtimeend_unixtime 为 0 的情况,也可以进一步扩展逻辑(例如判断是否为 0,决定是否加上该条件)。

    📌 示例扩展(可选):

    如果你还想根据 start_unixtimeend_unixtime 是否为 0 来动态添加条件,可以这样做:

    sql := "SELECT count(*) as chat_count FROM (SELECT DISTINCT(to_uid) FROM lu_live_report WHERE uid=?"
    
    args := []interface{}{streamer_id}
    
    if start_unixtime != 0 {
        sql += " AND create_at >= ?"
        args = append(args, start_unixtime)
    }
    
    if end_unixtime != 0 {
        sql += " AND create_at <= ?"
        args = append(args, end_unixtime)
    }
    
    sql += " AND (video_unix != 0 OR voice_unix != 0) GROUP BY to_uid) AS a"
    
    err := DbSlave.Raw(sql, args...).Scan(&total).Error
    return err
    

    ✅ 总结:

    • 使用参数绑定代替字符串拼接,确保安全性和正确性。
    • 动态构建 SQL 时,务必同步更新参数列表
    • 使用 args... 展开参数,使 GORM 能正确解析 SQL 中的占位符。

    如需进一步优化或处理更复杂的查询逻辑,也可以考虑使用 GORM 的链式查询方法(如 .Where().Group() 等)。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(4条)

报告相同问题?

问题事件

  • 系统已结题 10月24日
  • 已采纳回答 10月16日
  • 创建了问题 10月16日