2010-11-23 101 views
133

閱讀一些SQL調優文檔,我發現這一點:SQL:如何正確檢查是否存在記錄

Select count(*)
- 計數行
的數量 - 往往是使用不當,以驗證是否存在創紀錄

Select count(*)真的那麼糟糕?

什麼是驗證記錄存在的正確方法?

回答

163

這是更好地使用

select 1 
from table 
where key = value; 

select count(1) 
from table 
where key = value; 

第一個選擇應該給你任何結果或一個結果,第二計數應爲0或1。

您使用的文檔的年齡?雖然你已經閱讀了很好的建議,但是最近RDBMS中的大多數查詢優化器無論如何都優化了select count(*),所以儘管理論(和較老的數據庫)有所不同,但在實踐中你不應該注意到任何差異。

6

您可以使用:

SELECT COUNT(1) FROM MyTable WHERE ... 

WHERE [NOT] EXISTS 
(SELECT 1 FROM MyTable WHERE ...) 

這將是比SELECT *更有效,因爲你只是選擇值爲1的每一行,而不是所有的領域。

還有COUNT(*)和COUNT(列名)之間的微妙區別:

  • COUNT(*)將計算所有的行,包括空
  • 只會算非空列名的出現
+1

您錯誤地認爲DBMS會以某種方式檢查所有這些列。 `count(1)`和`count(*)`之間的性能差異只有在大腦死亡的DBMS中才會有所不同。 – paxdiablo 2010-11-23 08:20:58

+0

** @ paxdiablo **你是否建議依靠實現細節是一個好主意? – 2010-11-23 08:24:05

+2

不,我說你實際上依賴於實現細節,當你聲明它會更有效率。如果你真的想確保你獲得最佳性能,你應該使用具有代表性的數據來​​描述它的具體實現,或者完全忘記它。其他任何東西都可能會引起誤解,並且在從DB2移動到MySQL時可能會發生巨大變化。 – paxdiablo 2010-11-23 08:30:29

12

您可以使用:

SELECT 1 FROM MyTable WHERE <MyCondition> 

如果沒有匹配條件的記錄,則結果記錄集爲空。

126

我寧願不要使用計數功能在所有:

IF [NOT] EXISTS (SELECT 1 FROM MyTable WHERE ...) 
    <do smth> 

例如,如果你想檢查用戶是否將其插入到數據庫中的查詢之前存在可以是這樣的:

IF NOT EXISTS (SELECT 1 FROM Users WHERE FirstName = 'John' AND LastName = 'Smith') 
BEGIN 
    INSERT INTO Users (FirstName, LastName) VALUES ('John', 'Smith') 
END 
12

其他答案相當不錯,但也可以加LIMIT 1(或the equivalent,防止檢查不必要的行。

6
SELECT COUNT(1) FROM MyTable WHERE ... 

將循環所有記錄。這就是使用記錄存在不好的原因。

我會用

SELECT TOP 1 * FROM MyTable WHERE ... 

發現1次記錄後,將終止循環。

5

您可以使用:

SELECT 1 FROM MyTable WHERE... LIMIT 1 

使用select 1,以防止不必要的字段的檢查。使用LIMIT 1來防止檢查不必要的行。