檢查行是否存在
我需要編寫一個只插入一行的查詢,即使查詢執行多次。作為 SQL 新手(非常新),我做了一個,
if not exists(...)
但一位朋友說他更喜歡刪除該行(如果存在)然後再次添加它。
EXISTS
刪除或反之亦然的優點是什麼?- 還有另一種方法嗎?
有些人發現 DELETE-followed-by-INSERT 的程式碼更容易遵循,特別是如果要更新某些行以及要插入一些行,但我建議避免使用它。如果您確實使用此方法,請確保此或您的整個過程包含在事務中,以便如果出現問題,則不會發生任何事情(或者您可能會刪除一行然後無法插入更新)。
對於大量數據,尤其是當您希望行大部分時間已經存在時,DELETE+INSERT 的效率可能會大大降低:您有一個或兩個行修改操作(DEL+INS 而不是 INT 或 UPD)而不是 1 或 0(INS、UPD 或如果該行存在且正確,則沒有)將更新事務日誌和數據文件,以及包含您正在影響所有相關索引頁面的行的頁面將需要也更新了(兩次:一次用於刪除,一次用於插入)。對於少量數據,這種效率低下的問題可能不會很嚴重,但請牢記未來的可擴展性。除了可以立即測量的額外 I/O 操作外,您還可能會增加堆和/或索引碎片,從長遠來看這可能會導致其他性能問題。
如果您有一個正確定義的數據庫並實現了相關的外鍵關係,則 DELETE 操作可能會由於其他表中的條目引用的行而簡單地出錯,因此該技術絕對不能普遍使用。更糟糕的是,如果
ON DELETE CASCADE
使用了,您可能會無意中從其他地方刪除大量行,這些行不會被您後續的INSERT
. 如果設置了觸發器以對錶執行操作以影響其他地方的數據,則可能會出現類似問題。這是不養成習慣IMO的更重要原因。自 SQL2008 以來,INSERT-or-UPDATE 或 INSERT-or-NOTHING(或其他組合,包括刪除某些行)的最有效方法是新的 MERGE 語句。與 check+do 或 delete+insert 不同,結構只掃描一次,並且根據需要一次性完成所需的插入/更新/刪除操作。MSSQL 的 MERGE 語句與某些數據庫所稱的 UPSERT(更新或插入)操作沒有什麼不同(但更靈活)。其他數據庫中也有類似的操作:例如,IIRC,Oracle 在這方面實現了與 MSSQL 大致相同的功能。
編輯: 請參閱 Aaron 評論中的連結,了解重要的警告,以了解 MERGE 可能使其遠不如我建議的合適。