SQL: Bir kaydın var olup olmadığını düzgün bir şekilde kontrol etme


207

SQL Tuning ile ilgili bazı belgeleri okurken, şunu buldum:

SELECT COUNT(*) :

  • Satır sayısını sayar.
  • Genellikle bir kaydın varlığını doğrulamak için yanlış kullanılır.

SELECT COUNT(*)Gerçekten o kadar kötü?

Bir kaydın varlığını doğrulamanın doğru yolu nedir?

Yanıtlar:


252

Aşağıdakilerden birini kullanmak daha iyidir:

-- Method 1.
SELECT 1
FROM table_name
WHERE unique_key = value;

-- Method 2.
SELECT COUNT(1)
FROM table_name
WHERE unique_key = value;

İlk alternatif size hiçbir sonuç veya bir sonuç vermemelidir, ikinci sayı sıfır veya bir olmalıdır.

Kullandığınız belgeler kaç yaşında? İyi tavsiyeler okumuş olsanız da, yakın zamanda RDBMS'nin sorgu optimizatörlerinin çoğu SELECT COUNT(*)zaten optimize eder , bu nedenle teoride (ve eski veritabanlarında) bir fark olsa da, uygulamada herhangi bir fark görmemelisiniz.


1
Ben "anahtar = değer" yan tümcesi ile "benzersiz anahtar" amaçladı açıklayacağım ama bunun dışında hala benim cevap arkasında.
Martin Schapendonk

1
TAMAM. Bu önermeyle, sorgu sadece bir veya sıfır kayıt döndürür. AMA: Soru benzersiz bir sütunla sınırlı değil. Ayrıca: 2. sorgu sayısı (1), pratik bir POV'daki sayı (*) ile eşdeğerdir.
Martin Ba

1
Soru "A kaydının varlığını doğrulamanın doğru yolu nedir" diyor. Bunu tekil olarak yorumladım: 1 kayıt. Count (*) ve count (1) arasındaki fark zaten cevabım tarafından kapsanıyor. Belirli bir RDBMS uygulamasına bağlı olmadığından count (1) 'i tercih ederim.
Martin Schapendonk

192

Ben Say işlevini hiç kullanmayı tercih etmem:

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

Örneğin, kullanıcının veritabanına eklemeden önce var olup olmadığını kontrol etmek istiyorsanız, sorgu şöyle görünebilir:

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

Genellikle bir şey yapmak istediğinizde (doğrula) kullanırız, o zaman cevabınız daha eksiksizdir.
Abner Escócio

T-SQL'i kullanarak bahsetmek güzel
Bronek

20

Kullanabilirsiniz:

SELECT 1 FROM MyTable WHERE <MyCondition>

Koşulla eşleşen kayıt yoksa, sonuçta elde edilen kayıt kümesi boştur.


Şunu mu demek istedin TOP 1? -> (MyTable'DAN EN İYİ 1 SEÇİN <MyCondition>)
Jacob

6
Hayır, tam olarak "1" demek
istedim

1
Sorgu optimize edicinin kalan veri kümelerini okumayacağınıza / buna ihtiyacınız olmayacağını bile bilmesini sağlamak için, SEÇİN TOP 1 1 ... NEREDEN ... seçeneğini belirtmelisiniz (veya RDBS'niz için uygun sorgu ipuçlarını kullanın)
eFloh

3
Mevcut operatörün kendisi yalnızca minimum bilgi toplamını almaya çalışır, bu nedenle TOP 1'in eklenmesi sorgu boyutuna 5 karakter eklemek dışında hiçbir şey yapmaz. - sqlservercentral.com/blogs/sqlinthewild/2011/04/05/…
AquaAlex

13

Diğer cevaplar oldukça iyidir, ancak gereksiz satırların kontrolünü önlemek için LIMIT 1(veya eşdeğeri) eklemek de yararlı olacaktır .


3
Herhangi bir "varlığı kontrol" sorgusu birden fazla satır döndürürse, sonuç sayısını LIMIT-ing yerine WHERE yan tümcesini iki kez kontrol etmek daha yararlı olduğunu düşünüyorum.
Martin Schapendonk

2
Sanırım Limit Oracle'da kullanılıyor ve SQL Server'da değil
Shantanu Gupta

7
Meşru bir şekilde birden fazla satır olabilir durumda nerede düşünüyorum - nerede soru: "Bu koşulu karşılayan (bir veya daha fazla) satır var mı?" Bu durumda, hepsine bakmak istemezsiniz, sadece bir tane.
JesseW

1
@Shantanu - Biliyorum, bu yüzden diğer formları açıklayan en.wikipedia makalesine bağlandım.
JesseW

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

tüm kayıtlar arasında döngü yapacaktır. Kayıt varlığı için kullanmanın kötü olmasının nedeni budur.

Kullanmak istiyorum

SELECT TOP 1 * FROM MyTable WHERE ...

1 kayıt bulduktan sonra döngüyü sonlandıracaktır.


Durumunda SELECT TOP 1aslında bir bulduktan sonra sona erer veya hepsi TOP hangisi olduğunu söylemek mümkün bulmaya devam ediyor?
Eirik H

3
PS: Her zaman emin olmak içinIF EXISTS (SELECT TOP 1 1 FROM ... WHERE ..)
Eirik H

Yıldız işleci, DBMS'yi yalnızca birleştirme koşulunuz için gereken dizin (ler) yerine kümelenmiş dizine erişmeye zorlar. sonuç olarak sabit bir değer kullanmak daha iyidir, yani ilk 1 1'i seçin .... Bu duruma göre bir eşleşme olup olmadığına bağlı olarak 1 veya DB-Null değerini döndürür.
eFloh

bu iyi. Birinci olanı beğendim.
isxaker

10

Kullanabilirsiniz:

SELECT COUNT(1) FROM MyTable WHERE ... 

veya

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

Bu, SELECT *tüm alanlar yerine her bir satır için 1 değerini seçtiğinizden daha verimli olacaktır .

Ayrıca COUNT (*) ve COUNT (sütun adı) arasında küçük bir fark var:

  • COUNT(*) null dahil tüm satırları sayar
  • COUNT(column name)yalnızca sütun adının boş olmayan örneklerini sayar

2
Bir DBMS'nin bir şekilde tüm bu sütunları kontrol edeceğini yanlış varsayıyorsunuz. Arasındaki performans farkı count(1)ve count(*)sadece en beyin ölümü DBMS farklı olacaktır.
paxdiablo

2
Hayır, bunu söylüyorum size nasıl daha verimli olacak devlet zaman aslında uygulama ayrıntılarını güveniyorlar. Gerçekten en iyi performansı almanızı sağlamak istiyorsanız, temsili verileri kullanarak belirli bir uygulama için profil oluşturmalı veya tamamen unutmalısınız. Başka herhangi bir şey potansiyel olarak yanıltıcıdır ve DB2'den MySQL'e taşınırken (örneğin) büyük ölçüde değişebilir.
paxdiablo

1
Cevabınızı bozmadığımı açıklığa kavuşturmak istiyorum. O ise yararlıdır. Keşke biz beri verimlilik iddiası ile meseleyi bit yapılan DB2 / z değerlendirmeler ve arasında gerçek bir fark bulunuyor çevrede count(*)ve count(1). Diğer DBMS için durum böyle olsun, söyleyemem.
paxdiablo

3
"Başka bir şey potansiyel olarak yanıltıcıdır ve DB2'den MySQL'e taşınırken (örneğin) büyük ölçüde değişebilir" SEÇİM 1'i DBMS taşırken SELECT COUNT (*) ' un performans düşüşüyle ​​ısırılmanız daha olasıdır. veya COUNT (1). İstediğiniz davranışa varsayılan olarak optimize edicilere veya derleyicilere güvenmek yerine, tam olarak ne elde etmek istediğinizi açıkça ifade eden kodu yazarken sağlam bir inançlıyım.
Winston Smith

1
Yanıltıcı ifade "COUNT (*)", "satırların tam durmasını say" anlamına gelir. Belirli bir sütuna erişim gerektirmez. Ve çoğu durumda herhangi bir benzersiz indeks yeterli olduğu için satırın kendisine erişim gerektirmeyecektir.
James Anderson

9

Kullanabilirsiniz:

SELECT 1 FROM MyTable WHERE... LIMIT 1

select 1Gereksiz alanların kontrolünü önlemek için kullanın .

LIMIT 1 Gereksiz satırların kontrolünü önlemek için kullanın .


3
İyi bir nokta ama Limit MySQL ve PostgreSQL üzerinde çalışıyor, üst SQL Server üzerinde çalışıyor, cevabınıza dikkat etmelisiniz
Leo Gurdian

0

Bu şekilde kullanıyorum:

IIF(EXISTS (SELECT TOP 1 1 
                FROM Users 
                WHERE FirstName = 'John'), 1, 0) AS DoesJohnExist

0

Diğer seçenek:

SELECT CASE
    WHEN EXISTS (
        SELECT 1
        FROM [MyTable] AS [MyRecord])
    THEN CAST(1 AS BIT) ELSE CAST(0 AS BIT)
END
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.