<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          大型翻車現(xiàn)場:如何實現(xiàn)記錄存在就更新,如果記錄不存在就插入

          共 2782字,需瀏覽 6分鐘

           ·

          2021-09-30 11:34

          Hi,大家好!我是白日夢!下文以自導(dǎo)自演的方式,圍繞“如何實現(xiàn)記錄存在的話就更新,如果記錄不存在的話就插入。”展開本話題。看看你能抗到第幾問吧

          歡迎關(guān)注!持續(xù)更新中~

          1
          好!我們開始吧! 













                                        

          Hi同學(xué),前面表現(xiàn)的不錯哦。關(guān)于MySQL的基礎(chǔ)掌握的還可以,現(xiàn)在有時間繼續(xù)嗎?


          嗯,有時間!



          白日夢有話說是啊,那能掛嗎?這個專題還有好多文章沒寫完呢!掛了怎么往下寫?


          那我們繼續(xù)面吧。出一道場景題:現(xiàn)在我的業(yè)務(wù)中有這樣的需求:如果目標(biāo)記錄存在的話我就更新它,如果記錄不存在的話我就插入。說說看你知道哪些實現(xiàn)方式吧!


          嗯,比如我可以像下面這樣做


          這種方式。

          // 偽代碼user=User.FindById(1)if user == null{  user.Insert()}else{  user.Update()}



          嗯,這確實可以。但是你有更好的方式嗎?看你代碼,每次都是先查詢、再更新/寫入。至少都會和MySQL發(fā)生兩次網(wǎng)絡(luò)交互哦!

          嗯,還可以像下面這樣,我先嘗試更新,如果沒有這條記錄的話,更新函數(shù)返回的影響行數(shù)就是0。于是我根據(jù)這個影響行數(shù)去判斷,當(dāng)影響行數(shù)為0時說明數(shù)據(jù)庫中沒有這條記錄。于是我就寫入。



          ??通過這種方式和MySQL之間的網(wǎng)絡(luò)請求次數(shù)就有可能降低成1。

          // 偽代碼effectRows=User.UpdateById(1)if effectRows >0 {  user.Insert()}
          ?



          我看未必吧!并且你這代碼存在安全隱患啊!比如遇到這種情況:user實例中的信息和數(shù)據(jù)庫中的記錄完全一致。然后你拿著user中的信息去更新數(shù)據(jù)庫中的信息。實際上就沒有發(fā)生任何改變。也就是說,你的代碼中的UpdateById(1)的返回值是0!



          然后你的代碼進(jìn)入else中,很顯然id=1的行已經(jīng)存在了,你還執(zhí)行insert xxx id = 1,這肯定會報錯說:主鍵沖突啊!


          我靠!大佬說的對啊!按你這么說,這確實是個風(fēng)險。即使每次去更新的時候攜帶上最新的時間戳也無法保證它一定不會進(jìn)入到else中!




          嗯,對的。我們繼續(xù)這個話題,你還知道其他的實現(xiàn)方式嗎?我提示你一下:你有沒有使用過 insert ignore into 語句?


          嗯嗯,使用過,insert ignore into的作用是:如果記錄存在了就忽略本次ignore本次插入。如果記錄不存在就寫入。



          關(guān)于insert ignore into的實戰(zhàn)可以看這個示例


          Step1:創(chuàng)建庫表


          Step2:正常寫入一條數(shù)據(jù)


          Step3:使用insert ignore 重復(fù)寫入和上一條SQL完全一種的數(shù)據(jù)


          Step4:使用insert ignore寫入一條新的數(shù)據(jù),會發(fā)現(xiàn)可以寫入成功。


          Step5:使用insert ignore寫入,測試一下如果想寫入的數(shù)據(jù)的id(唯一key)已經(jīng)在表中存在了,其他的非唯一鍵數(shù)據(jù)不一樣。你會發(fā)現(xiàn):也不能重復(fù)寫入




          嗯,通過你的實驗可以看出:insert ignore into的功能是:如果數(shù)據(jù)已經(jīng)存在了就忽略本次寫入,如果數(shù)據(jù)不存在就insert。通過上面你做的實驗也可以看出它判斷是否可以寫入的標(biāo)準(zhǔn)是:唯一鍵不能重復(fù)。


          只要你想寫入的數(shù)據(jù)和現(xiàn)有的唯一鍵沖突了,最終就不會將你的數(shù)據(jù)落庫。


          嗯嗯,這么看來insert ignore into 并不能滿足我們的業(yè)務(wù)需求。不過我還了解 replace into




          嗯!那你說說這個replace 吧!


          ,replace into的作用是:如果數(shù)據(jù)已經(jīng)存在了我就更新。如果數(shù)據(jù)不存在就更寫入。


          而判斷數(shù)據(jù)是否已經(jīng)存在的標(biāo)準(zhǔn)依然是:判斷唯一鍵是否重復(fù)。




          嗯,繼續(xù)。


          嗯嗯,可以看下面的這個例子:


          Step1:如果數(shù)據(jù)不存在replace 可以將數(shù)據(jù)寫入進(jìn)去


          Step2:如果數(shù)據(jù)存在replace 可以使用新數(shù)據(jù)替換舊數(shù)據(jù)。


          而且這個替換還是全量替換:




          嗯,很好,使用replace into 確實能做到一次網(wǎng)絡(luò)請求就實現(xiàn)我們的業(yè)務(wù)需求。



          其實我還知道另一種實現(xiàn)方式:也可以通過一次網(wǎng)絡(luò)請求實現(xiàn)咱們的業(yè)務(wù)需求。




          哦?你說說看!


          使用 on duplicate key update也可以實現(xiàn),如果記錄存在就更新,如果記錄不存在就插入。



          關(guān)于: on duplicate key update可以看這個例子:


          Step1: 如果已經(jīng)存在了,就更新。


          Step2:如果不存在就寫入

          (上面兩圖中的ignore不影響)




          白日夢補(bǔ)充:下圖截自MySQL官網(wǎng),有一些值得我們注意的點(diǎn):


          其實你想一下,通常情況下,我們業(yè)務(wù)代碼中的insert語句是沒有指定主鍵的id等于多少的。因為這個主鍵會自己增加。官網(wǎng)中有描述:如果你每次使用on duplicate key update進(jìn)行更新時(注意是更新而不是插入),MySQL也會讓last_insert_id變大。這就會出現(xiàn)id不連續(xù)增長的現(xiàn)象。

          你可以看這個示例,我復(fù)現(xiàn)了一下主鍵id不連續(xù)增長的現(xiàn)象。

          Step1:創(chuàng)建數(shù)據(jù)表


          Step2:使用 on duplicate key update 寫入一條記錄。此時LAST_INSERT_ID為1


          Step3: 重復(fù)執(zhí)行,使用 on duplicate key update 將shanghai更新成beijing。此時LAST_INSERT_ID同樣會+1,變成2。


          Step4: 驗收結(jié)果的時刻來了。使用 on duplicate key update 插入name = hunan的行,注意觀察行的主鍵id為3。




          小伙子可以的!整體感覺還不錯。


          歡迎關(guān)注我。不久會給你安排下一面


          我沒有問題了,你有什么想問我的嗎?


          感謝大佬,點(diǎn)贊、在讀、打賞、轉(zhuǎn)發(fā)馬上安排上!





          《為研發(fā)同學(xué)定制的MySQL面試指南》 
          貫穿單機(jī)、集群、中間件!
          面試官都關(guān)注了!你還猶豫?



          往期精彩文章:


          誰會拒絕一臺Win11和MacOS無縫切換的MacBook呢?Parallels17極速體驗


          軟件開發(fā)的22條黃金法則


          使用AI在原神里自動釣魚,掃描Git倉庫泄露的密碼 【Github熱榜周刊第三期】


          從吳某凡事件中理解什么是"中間人攻擊"


          3分鐘搭建一個網(wǎng)站?騰訊云Serverless開發(fā)體驗


          瀏覽 46
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  免费一级色情视频 | 中国在线黄色电影 | 麻豆免费视频 | 国产精品午夜福利 | 日本综合在线观看 |