寫程式一段時間,發現每次遇到如果資料不存在就新增,如果存在就異動的這個情況,總是要用DBCommand去Execute個兩次,總是沒有辨法一次搞定,現在想到的方法就是從Script著手.
寫程式一段時間,發現每次遇到如果資料不存在就新增,如果存在就異動的這個情況,總是要用DBCommand去Execute個兩次,總是沒有辨法一次搞定,現在想到的方法就是從Script著手.
比如說,現在有個Table如下 :
Table Name : ExchangeRate
Column Name : CurrencyName , Rate
CurrencyName | Rate |
USD | 35 |
HKD | 4 |
現在有一筆資料進來,要去異動資料庫,如果沒有就新增,有就異動Rate,原有的做法如下 :
DBCmd.CommandText = "update ExchangeRate set Rate=:Rate where CurrencyName=:CurrencyName"; DBCmd.Parameters.Add(......... if (DBCmd.ExecuteNonQuery()==0) { DBCmd.CommandText="insert into ExchangeRate (CurrencyName,Rate) values (:CurrencyName,:Rate)" DBCmd.ExecuteNonQuery(); }
現在想到ExecuteNonQuery一次就搞定,就是從CommandText的Script著手.
DBCmd.CommandText = " DECLARE cnt number; begin select count(*) into cnt from ExchangeRate where CurrencyName=:CurrencyName; if cnt>0 then update ExchangeRate set Rate=:Rate where CurrencyName=:CurrencyName; else insert into ExchangeRate (CurrencyName, Rate) values (:CurrencyName,:Rate); end if; end; "; DBCmd.ExecuteNonQuery();
這樣就可以在呼叫ExecuteNonQuery()一次搞定,
這個Script是用Oracle的寫法,MS SQL也是一樣的原理.
至於那種效能好,看情況~~
===2010/7/9 補充 ===
這種方式在一般情況看來,似乎也沒比較好,這想法也沒錯,這要看資料情況及整體架構來決定,就假設一個情境來說.
現在有一個WinForm的程式,Client可能透過多種網路連結方式到Server,而有些據點只有ADSL 2M/256K,而這樣的頻寬下,有5台電腦共用,以ADSL的折耗以7成來算(很客氣了,有的只有5成),上傳頻寬約180K左右,有些人員在外面用NB是透過3.5G行動上網,所以這個情況看來,Client到Server這中間的網路頻寬是個瓶頸,尤其上傳頻寬.
Client現有一些有就異動,沒有就新增的資料要上傳到資料庫去,那要怎麼做,才能減輕網路的負擔?
如果是用第一種方式ExecuteNonQuery()兩次,那就無法使用DBCommand.Prepare()產生暫存的Store Procedure,因為沒有異動到資料,就要新增,CommandText就需要再異動,所以在每次ExecuteNonQuery()時,都會傳輸全部的CommandText及Parameters過去.
而第二種方式,雖然要Select之後再去判斷要Insert還是Update,但這個CommandText是固定的,就不需要再異動,這時就可以使用DBCommand.Prepare()產生暫存的SP,所以在每次ExecuteNonQuery()時,傳輸的資料量就較少,只要Parameters及系統會自動去Execute那個暫存SP.
當然這時如果能直接在資料庫新增一個Store Procedure去呼叫就好,就不需要使用DBCommand.Prepare()產生暫存的,但這個SP要怎麼寫? 難不成還是讓Client去ExecuteNonQuery()一或兩次嗎^^.
這個情境並不是什麼Worst Case,這是過去遇到的經驗,曾經有個據點把他們的網路頻寬吃光,什麼事都不用做了,客戶急的跳腳,我也想過,怎麼那個據點的網路不升速?確認後才知道,那個據點在郊區,那邊沒有鋪線,沒辨法申請更快的頻寬,除非自己出錢鋪線,那3.5G呢,該點也很不幸的,也沒有~~
所以我只能說看情況,選方法~