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

GORM Postgres Raw SQL UPDATE操作decimal类型相加报错如何解决

问题1:是否需要将decimal类型转为float处理?

绝对不要。float为非精确数值类型,转换后会出现精度丢失问题,完全不适合积分、金额这类对精度要求高的业务场景。

问题2:可以通过修改SQL或类型适配解决

报错的根本原因是Go的decimal.Decimal类型默认被GORM序列化为字符串传入SQL,PostgreSQL执行coins + ?时会识别为「text类型 + 未知类型」,触发类型不匹配错误。你可以选择以下两种方案解决:

方案1:直接修改Raw SQL语句(快速修复)

在占位符后显式指定转换为PostgreSQL原生支持的numeric类型即可,同时将decimal变量转为字符串传入,不会损失精度:

convertedCurr = points.Div(config.BaseFactor).Round(2)

// 给数值类型的参数占位符加::numeric显式类型转换
sqlCoins := "UPDATE coins SET coins = coins + ?::numeric, points = points + ?::numeric WHERE tenant = ? AND user_id = ?"
errUpdateCoins = database.GetDbWriteClient().Raw(sqlCoins, convertedCurr.String(), points.String(), tenant, userId).Scan(&coin).Count(&updatedCount).Error

方案2:自定义类型适配(长期通用方案)

给decimal.Decimal实现GORM要求的driver.Valuer和sql.Scanner接口,让GORM自动完成Go类型与PostgreSQL numeric类型的映射,后续所有SQL操作都不需要额外加类型转换:

import (
  "database/sql/driver"
  "fmt"
  "github.com/shopspring/decimal"
)

// 自定义Decimal类型适配GORM和PostgreSQL
type Decimal decimal.Decimal

// Value 实现driver.Valuer接口,写入数据库时自动转为字符串
func (d Decimal) Value() (driver.Value, error) {
  return decimal.Decimal(d).String(), nil
}

// Scan 实现sql.Scanner接口,读取数据库时自动解析为Decimal类型
func (d *Decimal) Scan(value interface{}) error {
  if value == nil {
    *d = Decimal(decimal.Zero)
    return nil
  }
  var str string
  switch v := value.(type) {
  case string:
    str = v
  case []byte:
    str = string(v)
  default:
    return fmt.Errorf("unsupported type for decimal scan: %T", value)
  }
  dec, err := decimal.NewFromString(str)
  if err != nil {
    return err
  }
  *d = Decimal(dec)
  return nil
}

之后将你的模型中coins、points字段的类型替换为上面自定义的Decimal类型,原SQL不需要任何修改即可正常执行。

补充优化建议

UPDATE类写操作建议用GORM的Exec方法替代Raw+Scan,写法更简洁:

res := database.GetDbWriteClient().Exec(sqlCoins, convertedCurr, points, tenant, userId)
errUpdateCoins = res.Error
updatedCount = res.RowsAffected

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 14:36:03