SQL 更新 vs. INSERT vs. UPSERT

本文探討三個 SQL 陳述:更新、插入和 UPSERT。其中包含使用方式與時機的範例。

SQL UPDATE vs. INSERT vs. UPSERT

image_pdfimage_print

在任何應用程式中,您都必須將記錄新增至資料庫表格,並變更儲存的資訊。更新 SQL 陳述式會變更儲存在資料庫中的資料,而 INSERT 陳述式會將新的記錄加入表格中。UPSERT 聲明是 INSERT 和 UPDATE 的組合,若記錄不存在,則執行更新或新增記錄。在這裡,我們將討論 SQL 更新 vs. INSERT vs. UPSERT。

如何在 SQL 中使用更新:範例

更新聲明會以您指定的新資訊更新目前記錄。例如,客戶可能會移動並變更電子商務表格中的聯絡資訊,而更新聲明則將執行變更。您在資料庫中所做的任何變更都將使用 UPDATE 聲明。

重要的是要注意,優化查詢可降低資料庫延遲。最佳化的 UPDATE 查詢可將資料處理時間縮短至幾毫秒。基礎架構對於大容量資料庫伺服器的低延遲也很重要。使用以下查詢開始。經常更新的索引欄有助於提升效能。在大型並行工作負載中,資料庫開發人員可能必須使用隔離等級來防止聲明也影響其他聲明的處理。

除此之外,開發人員和資料庫管理員的程式碼應該會發生錯誤。這些範例顯示如何執行每個指令,但您的業務邏輯應決定在錯誤觸發時該怎麼做。例如,如果資料庫無法插入新的客戶記錄,請通知使用者再試一次,或聯絡客戶服務。資料庫延遲、錯誤和最佳化警告可透過效能監控工具達成。

在 SQL 中更新:範例

對於大多數 SQL 更新陳述,您都使用 WHERE 條款。WHERE 條款決定哪些記錄將被更新,而其他記錄則保持不變。如果您在執行 UPDATE 聲明時未使用 WHERE 條款,資料庫將對資料庫中的所有記錄進行變更,這可能是一個錯誤。確保 SQL 陳述式中有 WHERE 條款,以避免此錯誤。

UPDATE 陳述式語法取決於您使用的資料庫引擎。MySQL 和 Oracle SQL 資料庫的更新陳述使用類似的語法。以下範例將客戶的名字改為 “john”,其中客戶的 ID 為 44。

如何在 SQL 中使用 INSERT:範例

當您要將新記錄新增至表格中時,請使用 INSERT SQL 陳述式。大多數資料庫設計者會建立預設欄,為每一筆記錄提供唯一識別碼。唯一識別碼會自動填入,因此您不必手動插入,並允許資料庫引擎為您執行。您無法將重複值插入識別碼列,因此讓資料庫為您進行此作業會更有效率。

在以下範例中,新客戶會新增至客戶表格中,並在適當的欄中填入名字和姓氏。請注意,各欄的定義與要分別加入各欄的值。

如何在 SQL 中使用 UPSERT:範例

UPSERT 指令是非常有用的陳述,只有在資料行不存在時才要插入資料行。如果它已經存在,則資料庫會更新記錄,而改用新資訊。Oracle 資料庫引擎有特定的 UPSERT 指令。使用 MySQL 時,命令會改用 REPLACE 一詞。

應用程式開發人員使用 UPSERT 指令來避免重複記錄,尤其是當他們擁有與之連結的唯一識別碼時,應用程式聲明不應因先前存在的記錄而插入記錄。當您將資料從一個表格匯入到另一個表格時,通常會發生這種情形,而且可能存在重複的記錄。例如,您從收購的企業取得客戶記錄清單,並知道有些客戶已經在目前的企業資料庫中。UPSERT 聲明只會更新現有客戶,並新增不存在的新客戶。

在上述範例中,如果識別碼為 44 的客戶已經存在,原始記錄將被刪除,然後新增識別碼為 44 的新客戶記錄。請務必記住,REPLACE 指令不會在技術上更新任何資料。而是刪除並重新新增列至表格中。

使用 Oracle,UPSERT 指令會以 44 的識別碼更新客戶,而不是刪除並重新新增。如果記錄不存在,Oracle 引擎會將客戶記錄加入表格中。

PostGreSQL 沒有特定的 UPSERT 陳述式,但它支援一種 INSERT,伺服器只有在新的記錄不存在時,才會插入它。如果記錄存在,表格限制應捨棄錯誤,並執行 UPDATE 而非 INSERT 陳述式。PostGreSQL 語法如下:

Microsoft SQL Server 也不支援 UPSERT 陳述式,但開發人員可以使用 MERGE 命令來執行類似動作。MERGE 陳述式會取得來源資料集,並將其與表格合併,但只有在資料列不存在時才插入新記錄。如果列存在,MERGE 陳述式將更新記錄。 

MongoDB 有一個 UPDATE 指令參數,可告訴資料庫執行 UPSERT 陳述式。與其他資料庫一樣,MongoDB 只有在記錄不存在時才會插入新記錄。如果確實存在,資料庫將執行並更新記錄。

更新 vs. 插入:SQL 的差異

大多數應用程式使用數個 UPDATE 和 INSERT 陳述式來管理資料。當您需要新增記錄時,必須插入對帳單。當您需要變更已儲存的資料時,必須更新聲明。

INSERT 陳述式需要所有必須填入必要值的欄。更新聲明不需要 WHERE 條款,但如果排除,所有記錄都會以特定資料進行更新。您不太可能想要更新所有記錄,因此請務必包含 WHERE 條款。

您無法用 UPDATE 取代 INSERT,但 UPSERT 聲明是很好的替代方案。使用 UPSERT 聲明,資料庫會更新可用記錄,如果記錄不存在,則將其插入表格中。INSERT 比 UPDATE 聲明更快,前提是資料庫已妥善優化。

UPSERT vs. 更新與插入:哪一個比較好?

您使用的陳述取決於您要如何處理資料庫中的資料。就效能而言,INSERT 比 UPSERT 更好,但您無法避免使用更新聲明,需要一種方法來驗證記錄不存在。UPSERT 聲明簡化了整個流程,而不必在儲存的程序中寫出較長的 IF 聲明。當您有大量更新或插入對帳單以匯入資料,而不希望重複時,UPSERT 對帳單的效能會更好。您一次完成更新和插入。

何時在 SQL 中使用更新

資料庫表中唯一變更資料的方式,就是使用 UPDATE 聲明。應用程式會因各種原因不斷變更資料,並在後端使用 SQL 更新聲明。當您在線上變更帳號的聯絡資訊、信用卡資料或運送地址時,後端應用程式系統很可能會執行更新對帳單。

當您只需要編輯資料時,請使用更新,而重複資料並非問題。簡單的 UPDATE 陳述式並不慢,但需要編輯的欄和列越多,可能會減慢資料庫服務的速度。在非尖峰時段執行大批更新聲明可能會有所幫助。

何時在 SQL 中使用 INSERT

當您要將記錄新增至表格時,需要 INSERT 陳述式。每當您註冊應用程式,或從電子商務商店訂購新產品時,後端資料庫使用 INSERT SQL 陳述式將新記錄加入資料庫。新的記錄之後可以用 UPDATE 陳述式變更,但先用 INSERT 陳述式建立。

INSERT 陳述式通常快速。當您需要新增記錄時,這是無法避免的。如同 UPDATE 聲明,如果大型插頁(例如從靜態檔案匯入資料)在非尖峰時段運行,則可能會更妥善地優化。稽核與記錄的記錄檔案使用簡易的 INSERT 陳述式。

何時在 SQL 中使用 UPSERT

UPSERT 陳述式在所有三個指令中都具有最低的效能,但當您有數筆記錄要新增至表格,但不想重複時,它就有其目的。當您將資料匯入表格中,並認為可能有重複的記錄時,請使用 UPSERT 聲明來更新目前的記錄,而非新增重複的記錄。例如,如果您需要將客戶從外部檔案匯入資料庫表格,則 UPSERT 聲明可能比使用 INSERT 聲明更合適。

如果您擁有可能有重複的大型來源資料集,則 UPSERT 聲明通常很有幫助。例如,您不想複製產品表,所以您會使用 UPSERT 來代替使用一個 INSERT 陳述式,之後再移除重複內容。當您有大量資料時,UPSERT 是很棒的,但如果它們被用於所有不必要的 INSERT 陳述式,則可能會導致延遲問題。只有在您可以將重複項目匯入主表格時,才能使用 UPSERT。

常見問答

UPSERT 通常比手動捲起的 “select then insert” 邏輯在高並行性下更安全,因為衝突偵測與解決是在單一原子作業中處理。您仍然需要確保有正確的索引和獨特的限制,以便資料庫能夠快速解決衝突,並避免不必要的鎖定或爭論。

防止重複的最可靠方法是在欄或一組欄上定義一個主鍵或唯一限制,必須唯一,然後圍繞該限制寫上您的 INSERT 或 UPSERT。資料庫引擎將在寫入時強制執行唯一性,這比嘗試手動檢查應用程式程式碼中的現有列更可靠。

當您經常需要根據使用者 ID 或訂單 ID 等金鑰建立或更新相同的記錄時,UPSERT 最有用。它簡化了應用邏輯,降低了“檢查然後插入”模式導致的比賽情況的機會,並且通常比發出單獨的INSERT和UPDATE陳述式時,導致資料庫的往返次數更少。

INSERT 新增一列, 更新 會變更已符合您標準的現有列,而 UPSERT 則透過插入新列來結合兩種行為,或在找不到符合項目時更新現有列。從“創造”、“修改”和“創造或修改”的角度思考,可以幫助您為每個使用案例選擇正確的陳述。