Golang:重复键值违反唯一约束
Posted
技术标签:
【中文标题】Golang:重复键值违反唯一约束【英文标题】:Golang: duplicate key value violates unique constraint 【发布时间】:2022-01-13 21:26:17 【问题描述】:当我尝试将两个或多个寄存器插入 for 循环时出现此错误,第一个工作正常但随后出现错误,数据库是新的,我已经重新创建了很多次
pq: duplicate key value violates unique constraint \"movements_pkey\
我有我的动作模型
type Movement struct
ID int `gorm:"primary_key" json:"id"`
Amount float32 `json:"amount"`
FkType *int `gorm:"column:fk_type" json:"fk_type"`
Type Type `gorm:"foreignkey:FkType"`
FkIncome int `gorm:"column:fk_income" json:"fk_income"`
Income Incoming `gorm:"foreignkey:FkIncome"`
FkOrder *int `gorm:"column:fk_order" json:"fk_order,omitempty"`
CreatedAt *time.Time `json:"created_at"`
这里是我在 for 循环中调用函数以保存在数据库 (MovementCreate) 中的地方,第一个总是成功创建,但第二个给我这个错误,尝试创建新记录但显然 postgresql 采取相同的最后一个ID
func (w *WebServices) CreateMovementMoneyOut(dataMovement *validators.MovementValidator) ([]models.IncomingResult, error)
nameFile := "Movement Services"
dataWallet, err := w.wallet.FindWalletByCustomerID(dataMovement.FKCustomer)
if err != nil
utils.LogService(nameFile, "Wallet Find", err.Error(), "error")
return nil, err
if (dataWallet.Amount <= 0) || !(*dataMovement.FkType == 2)
utils.LogService(nameFile, "Wallet Update", "Insufficients funds", "error")
return nil, fmt.Errorf("Insufficients funds")
incomingUpdate, err := w.incoming.UpdateIncomingsByFkWallet(&dataWallet.ID, *dataMovement.Amount)
var movement models.Movement
for _, val := range incomingUpdate
movement.Amount = val.Amount
movement.FkIncome = val.ID
movement.FkType = dataMovement.FkType
movement.FkOrder = dataMovement.FkOrder
_, err := w.movement.MovementCreate(&movement)
if err != nil
utils.LogService(nameFile, "CreateMovementMoneyOut", err.Error(), "error")
return nil, err
newAmount, err := w.incoming.CalculateWalletAmount(&dataWallet.ID)
if err != nil
utils.LogService(nameFile, "Wallet Update", err.Error(), "error")
_, err = w.wallet.WalletUpdateAmount(dataWallet, newAmount)
if err != nil
utils.LogService(nameFile, "Wallet Update", err.Error(), "error")
return nil, err
return incomingUpdate, nil
保存到数据库时在此处
func (s *WalletService) MovementCreate(data *Movement) (*Movement, error)
result := s.Create(data)
return data, result.Error
控制台报错的完整响应是这样的
2021/12/08 20:57:18 /usr/src/app/pkg/datalayers/models/movement.go:45 pq: duplicate key value violates unique constraint "movements_pkey"
[1.249ms] [rows:0] INSERT INTO "movements" ("amount","fk_type","fk_income","fk_order","created_at","id") VALUES (1000.000000,2,7,1,'2021-12-08 20:57:16.173',16) RETURNING "id"
16是循环中第一次迭代成功创建的最后一个id,下一次迭代尝试使用相同的id但新记录的数据正确
【问题讨论】:
上面代码中的motion.ID分配在哪里。请确保每次在循环内都将其覆盖,或者您可以在循环内声明移动变量以确保不会继续前一个循环的数据。WalletService.Create
中发生了什么。此外,由于您的 id 是一个 int - 我猜您可能还需要结构中的 autoIncrement 字段标记 - 不过请先检查您的表详细信息(\d tablename
)。如果您自己处理,请忽略。
【参考方案1】:
如果您使用的是gorm V2
,请将primary_key
替换为primaryKey
,并添加autoIncrement
,默认情况下为true
。如果您愿意,您可以添加 Unique
约束,这取决于您。
type Movement struct
ID uint64 `gorm:"primaryKey;autoIncrement" json:"id"` //Change it
Amount float32 `json:"amount"`
FkType *int `gorm:"column:fk_type" json:"fk_type"`
Type Type `gorm:"foreignkey:FkType"`
FkIncome int `gorm:"column:fk_income" json:"fk_income"`
Income Incoming `gorm:"foreignkey:FkIncome"`
FkOrder *int `gorm:"column:fk_order" json:"fk_order,omitempty"`
CreatedAt *time.Time `json:"created_at"`
您需要为每组数据创建一个对象。在 for 循环中添加 var movement models.Movement
。
而且你不需要提及movement.ID
,默认情况下它会被gorm很好地处理。
for _, val := range incomingUpdate
var movement models.Movement //Update it
movement.Amount = val.Amount
movement.FkIncome = val.ID
movement.FkType = dataMovement.FkType
movement.FkOrder = dataMovement.FkOrder
_, err := w.movement.MovementCreate(&movement)
if err != nil
utils.LogService(nameFile, "CreateMovementMoneyOut", err.Error(), "error")
return nil, err
【讨论】:
谢谢!我将运动移入循环并开始工作。我还在用 gorm 1.9以上是关于Golang:重复键值违反唯一约束的主要内容,如果未能解决你的问题,请参考以下文章