2014-01-21 69 views
1

我有另外一個程序員誰寫了一堆d​​elete語句看起來像這樣的:SQL「中的」與加入進行刪除

DELETE dbo.Test WHERE TestId IN (SELECT TestId FROM #Tests) 

(這一個很簡單但也有其他與子和子子在這樣的陳述)

我總是把這些類型的語句寫成連接。在我看來,這就像有一個將被反覆調用的內聯函數。然而,我知道優化器能夠帶來一些嚴重的魔法,而且新事物總是被添加進去。我還沒有研究過Join和In之間的區別,我想我會問,如果它仍然是一個應該加入的東西。

如果您使用「加入」或「中」,這有什麼關係?

回答

3

大多數現代SQL優化器會從這樣的子句中找出​​一個連接,但不能保證,查詢得到越複雜,優化器將選擇適當的動作的可能性就越小。

作爲一般規則,在這種情況下使用IN不是一種好的做法。 (個人意見警告)這實際上並不意味着以這種方式使用。

一個好的經驗法則(同樣,這是有爭議的,但不是錯誤的),因爲使用IN,堅持有限列表。例如:

SELECT DISTINCT * FROM foo WHERE id IN (1, 2, 3, ...); 

當對另一臺去,其中之一是優選的:

SELECT DISTINCT f.* FROM foo AS f 
INNER JOIN bar as b on b.foo_id = f.id; 

SELECT DISTINCT * FROM foo AS f 
WHERE EXISTS (SELECT NULL FROM bar AS b WHERE b.foo_id = f.id); 

取決於你在做什麼,你的數據的性質,您的里程將這些變化。

請注意,在這個簡單的示例中,IN,JOINEXISTS很可能會生成完全相同的查詢計劃。但是,當您開始針對多個表開發一些嚴重的業務邏輯時,您可能會發現查詢計劃顯着不同。

+0

如果'in'不是這樣使用的,那麼它是如何使用的?我看不出這種用法有什麼問題 - 有些DBMS甚至不支持在'delete'語句中的連接,那裏沒有替代方法,它們的表現也一樣好。並且:連接不一定代替IN條件,兩種服務器都有不同的用途,並可能返回不同的結果。 –

+0

@a_horse_with_no_name「IN」通常用於與有限值列表一起使用,以與列值進行比較。一般來說,除非實際上有一個有限的列表來反對,否則你希望使用'EXISTS'子句或'JOIN'而不是'IN'。一般來說,這會產生更一致的結果。 –

0

最有效的途徑是

Delete t1 
From table1 t1 
Inner Join table2 t2 on t1.col1=t2.col2 

table2您可以指定臨時表(#Tests),這會快很多。

2

有三種方法可以查看代碼。它在功能上有效嗎?它是否提供良好的代碼維護/可讀性?它表現不錯嗎?

從功能上講,如果兩者都執行相同的操作,則在編寫IN子句或使用連接之間沒有區別。

從維護/可讀性方面來看,人們可能會認爲,在簡單情況下,連接語法會很簡單。但是,如果IN子句中使用的子查詢是一個複雜的多連接操作,那麼以後可能會更具描述性,更易於調試(將自己置於必須查看代碼的人的腳下在有限的背景下。)

最後,從性能的角度來看,這取決於表中的行數,可用的索引(包括它們的統計數據)以及基於成本的優化器如何處理查詢(這可能因SQL版本而異)至於哪個表現會更好。

因此,與IT領域的大多數決策一樣,真正的答案是...... 它取決於