導讀
Hi,大家好!我是白日夢!本文是MySQL專題的第 26 篇。
下文還是白日夢以自導自演的方式,圍繞“如何實現記錄存在的話就更新,如果記錄不存在的話就插入。”展開本話題。看看你能抗到第幾問吧
換一種寫作風格,自導自演面試現場!感覺這樣還是比較有趣的,歡迎大家訂閱我的MySQL專題,公眾號首發!持續更新中~
歡迎關注白日夢,公眾號首發!持續連載中
Hi同學,前面表現的不錯哦。關於MySQL的基礎掌握的還可以,現在有時間繼續嗎?
嗯,有時間!
那我們繼續面吧。出一道場景題:現在我的業務中有這樣的需求:如果目標記錄存在的話我就更新它,如果記錄不存在的話我就插入。說說看你知道哪些實現方式吧!
這種方式。
// 虛擬碼user=User.FindById(1)if user == null{ user.Insert()}else{ user.Update()}
嗯,還可以像下面這樣,我先嚐試更新,如果沒有這條記錄的話,更新函式返回的影響行數就是0。於是我根據這個影響行數去判斷,當影響行數為0時說明資料庫中沒有這條記錄。於是我就寫入。
通過這種方式和MySQL之間的網路請求次數就有可能降低成1。
// 虛擬碼effectRows=User.UpdateById(1)if effectRows >0 { user.Insert()}
我看未必吧!並且你這程式碼存在安全隱患啊!比如遇到這種情況:user例項中的資訊和資料庫中的記錄完全一致。然後你拿著user中的資訊去更新資料庫中的資訊。實際上就沒有發生任何改變。也就是說,你的程式碼中的UpdateById(1)的返回值是0!
然後你的程式碼進入else中,很顯然id=1的行已經存在了,你還執行insert xxx id = 1,這肯定會報錯說:主鍵衝突啊!
我靠!大佬說的對啊!按你這麼說,這確實是個風險。即使每次去更新的時候攜帶上最新的時間戳也無法保證它一定不會進入到else中!
嗯,對的。我們繼續這個話題,你還知道其他的實現方式嗎?我提示你一下:你有沒有使用過 insert ignore into 語句?
嗯嗯,使用過,insert ignore into的作用是:如果記錄存在了就忽略本次ignore本次插入。如果記錄不存在就寫入。
關於insert ignore into的實戰可以看這個示例
Step1:建立庫表
Step2:正常寫入一條資料
Step3:使用insert ignore 重複寫入和上一條SQL完全一種的資料
Step4:使用insert ignore寫入一條新的資料,會發現可以寫入成功。
Step5:使用insert ignore寫入,測試一下如果想寫入的資料的id(唯一key)已經在表中存在了,其他的非唯一鍵資料不一樣。你會發現:也不能重複寫入
嗯,通過你的實驗可以看出:insert ignore into的功能是:如果資料已經存在了就忽略本次寫入,如果資料不存在就insert。通過上面你做的實驗也可以看出它判斷是否可以寫入的標準是:唯一鍵不能重複。
只要你想寫入的資料和現有的唯一鍵衝突了,最終就不會將你的資料落庫。
嗯嗯,這麼看來insert ignore into 並不能滿足我們的業務需求。不過我還了解 replace into。
嗯!那你說說這個replace 吧!
好,replace into的作用是:如果資料已經存在了我就更新。如果資料不存在就更寫入。
而判斷資料是否已經存在的標準依然是:判斷唯一鍵是否重複。
嗯,繼續。
嗯嗯,可以看下面的這個例子:
Step1:如果資料不存在replace 可以將資料寫入進去
Step2:如果資料存在replace 可以使用新資料替換舊資料。
而且這個替換還是全量替換:
嗯,很好,使用replace into 確實能做到一次網路請求就實現我們的業務需求。
其實我還知道另一種實現方式:也可以通過一次網路請求實現我們們的業務需求。
哦?你說說看!
使用 on duplicate key update也可以實現,如果記錄存在就更新,如果記錄不存在就插入。
關於: on duplicate key update 可以看這個例子:
Step1: 如果已經存在了,就更新。
Step2:如果不存在就寫入
(上面兩圖中的ignore不影響)
小夥子可以的!整體感覺還不錯。
不久會給你安排下一面。
我沒有問題了,你有什麼想問我的嗎?
感謝大佬,歡迎關注我,點贊、在讀、打賞、轉發馬上安排上!
推薦閱讀
- MySQL的修仙之路,圖文談談如何學MySQL、如何進階!(已釋出)
- 面前突擊!33道資料庫高頻面試題,你值得擁有!(已釋出)
- 大家常說的基數是什麼?(已釋出)
- 講講什麼是慢查!如何監控?如何排查?(已釋出)
- 對NotNull欄位插入Null值有啥現象?(已釋出)
- 能談談 date、datetime、time、timestamp、year的區別嗎?(已釋出)
- 瞭解資料庫的查詢快取和BufferPool嗎?談談看!(已釋出)
- 你知道資料庫緩衝池中的LRU-List嗎?(已釋出)
- 談談資料庫緩衝池中的Free-List?(已釋出)
- 談談資料庫緩衝池中的Flush-List?(已釋出)
- 瞭解髒頁刷回磁碟的時機嗎?(已釋出)
- 用十一張圖講清楚,當你CRUD時BufferPool中發生了什麼!以及BufferPool的優化!(已釋出)
- 聽說過表空間沒?什麼是表空間?什麼是資料表?(已釋出)
- 談談MySQL的:資料區、資料段、資料頁、資料頁究竟長什麼樣?瞭解資料頁分裂嗎?談談看!(已釋出)
- 談談MySQL的行記錄是什麼?長啥樣?(已釋出)
- 瞭解MySQL的行溢位機制嗎?(已釋出)
- 說說fsync這個系統呼叫吧! (已釋出)
- 簡述undo log、truncate、以及undo log如何幫你回滾事物! (已釋出)
- 我勸!這位年輕人不講MVCC,耗子尾汁! (已釋出)
- MySQL的崩潰恢復到底是怎麼回事? (已釋出)
- MySQL的binlog有啥用?誰寫的?在哪裡?怎麼配置 (已釋出)
- MySQL的bin log的寫入機制 (已釋出)
- 刪庫後!除了跑路還能幹什麼?(已釋出)
- 自導自演的面試現場,趣學資料庫的10種檔案(已釋出)
- 大型面試現場:一條update sql執行都經歷什麼?(已釋出)
- 大型翻車現場:如何實現記錄存在的話就更新,如果記錄不存在的話就插入。(已釋出)
最後,歡迎關注白日夢的公號哦~
換一種寫作風格,自導自演面試現場!感覺這樣還是比較有趣的,歡迎大家訂閱我的MySQL專題,公眾號首發!持續更新中~