亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

防止 GORM 在一個重復的主鍵錯誤后放棄 INSERT

防止 GORM 在一個重復的主鍵錯誤后放棄 INSERT

Go
一只甜甜圈 2023-02-14 15:42:06
我從 API 中提取數據。拉取結果生成結構數組,每個數組包含 100 個元素。我用來將它們插入數據庫的代碼是:   func (ACUpdater) InsertToTable(rawData *models.Contacts, table *gorm.DB) {    for i := 0; i < len(rawData.Results); i++ {        temp := models.ACQ_report{            ID :                           "",  //to be created later by hashing below data fields            RecordID:                      rawData.Results[i].ID,            FirstName:                     rawData.Results[i].Properties.Firstname,            LastName:                      rawData.Results[i].Properties.Lastname,            Email:                         rawData.Results[i].Properties.Email,            PhoneNumber:                   rawData.Results[i].Properties.Phone,            ContactOwner:                  rawData.Results[i].Properties.HubspotOwnerID,            CompanyName:                   rawData.Results[i].Properties.Company,        }        temp.ID = hashContactRecord(&temp)        table.Create(&temp)        fmt.Println(&temp)        fmt.Println(i)    }}我使用數據字段的散列作為表的主鍵,因此如果這些數據字段中的任何一個發生變化,散列也會發生變化。這樣,我就可以將已更改的記錄附加到現有表中,而不必擔心重復的主鍵。INSERTING問題是,在 GORM 出現 1 個重復主鍵錯誤后,上述功能完全“放棄” 。如果要插入數據庫的第一條記錄是重復的,那么tx.Created(&temp)仍然會運行,但不會插入更改的記錄。好像tx.Create()在第一個重復的主鍵錯誤之后放棄了。如何修復此行為?
查看完整描述

1 回答

?
鴻蒙傳說

TA貢獻1865條經驗 獲得超7個贊

這里的第一個問題可能掩蓋了實際的根本原因,即您沒有檢查是否INSERT返回錯誤。你會這樣做:


result := tx.Create(&temp)

if result.Error != nil {

  // handle it somehow

}

如果你這樣做并檢查錯誤,你可能會看到一些東西:


錯誤:重復鍵值違反唯一約束

即使您還看到以下錯誤,您也可能會看到這一點。在這種情況下,您的 INSERT 正在執行,但失敗了。如果您沒有看到任何其他錯誤并且只打印一次,那么您可能傳入了一個 gorm.DB 句柄,該句柄已鏈接到數據庫會話,并且會在第一個錯誤時失敗。


例如,如評論中所述,如果將結果傳遞db.Table("my_table")給此方法,則將出現上述情況。要修復它,只需傳遞db或db.NewSession(),并更新您的方法以指定表(或模型,更像 Gorm):


result := db.Table("my_table_name").Create(&temp)

if result.Error != nil {

  // ...

}

選項 2:錯誤:當前事務被中止,命令被忽略,直到事務塊結束

如果您看到這一點,則意味著您的方法正在事務中運行它的插入。這對你來說并非如此,但由于這是一個通用論壇,我將在此處留下這個和下面的解釋:在 Postgres 中,如果任何語句在事務中失敗,你不能執行任何進一步的語句,除了 ROLLBACK .

要解決此問題,您有幾種選擇:

  1. 在嘗試插入之前進行更多的數據驗證,直到您可以可靠地預期每次插入都會成功。您還可以使用 Gorm 的批量插入功能通過這種方法優化插入。

  2. 不要使用事務。如果您可以接受跳過的行,并且不擔心重復,那么這是一個合理的選擇。

  3. 使用保存點。在 Postgres 中,SAVEPOINT 類似于事務中的檢查點,您可以回滾到它而不是回滾整個事務,這正是您想要的:

tx.SavePoint("sp1")            // SAVEPOINT sp1;

result := tx.Create(&temp)

if result.Error != nil {

  tx.RollbackTo("sp1")         // ROLLBACK TO sp1;

}


查看完整回答
反對 回復 2023-02-14
  • 1 回答
  • 0 關注
  • 458 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號