Golang:重复键值违反唯一约束
Golang: duplicate key value violates unique constraint
当我尝试将两个或更多寄存器插入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但新记录的正确数据
如果您使用的是 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
}
}
当我尝试将两个或更多寄存器插入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但新记录的正确数据
如果您使用的是 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
}
}