web-dev-qa-db-fra.com

Sql: Comment vérifier correctement si un enregistrement existe

En lisant certains SQL Tuning documentation j'ai trouvé ceci:

Select count(*):
- Compte le nombre de lignes
- est souvent utilisé de manière inappropriée pour vérifier l'existence d'un document

Est-ce que Select count(*) est vraiment si mauvais? 

Quelle est la bonne façon de vérifier l'existence d'un enregistrement?

164
systempuntoout

Il est préférable d'utiliser l'un des éléments suivants:

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

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

La première alternative ne devrait vous donner aucun résultat ou un résultat, le second compte devrait être zéro ou un.

Quel âge a la documentation que vous utilisez? Bien que vous ayez lu de bons conseils, la plupart des optimiseurs de requêtes des SGBDR récents optimisent SELECT COUNT(*) de toute façon. Ainsi, même s’il existe une différence théorique (et dans des bases de données plus anciennes), vous ne devriez pas remarquer de différence dans la pratique.

202
Martin Schapendonk

Je préférerais ne pas utiliser la fonction Count du tout:

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

Par exemple, si vous voulez vérifier si l'utilisateur existe avant de l'insérer dans la base de données, la requête peut ressembler à ceci:

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

Vous pouvez utiliser:

SELECT 1 FROM MyTable WHERE <MyCondition>

Si aucun enregistrement ne correspond à la condition, le jeu d'enregistrements obtenu est vide.

18
Cătălin Pitiș

Les autres réponses sont assez bonnes, mais il serait également utile d’ajouter LIMIT 1 (ou l’équivalent , pour éviter la vérification des lignes inutiles.

12
JesseW

Vous pouvez utiliser:

SELECT COUNT(1) FROM MyTable WHERE ... 

ou

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

Cela sera plus efficace que SELECT * puisque vous sélectionnez simplement la valeur 1 pour chaque ligne, plutôt que tous les champs.

Il y a aussi une différence subtile entre COUNT (*) et COUNT (nom de colonne):

  • COUNT(*) comptera toutes les lignes, y compris les valeurs nulles
  • COUNT(column name) comptera seulement occurrences non nulles du nom de la colonne
10
Winston Smith
SELECT COUNT(1) FROM MyTable WHERE ...

passera en boucle dans tous les enregistrements. C’est la raison pour laquelle il est mauvais d’utiliser l’enregistrement.

J'utiliserais

SELECT TOP 1 * FROM MyTable WHERE ...

Après avoir trouvé 1 enregistrement, la boucle sera terminée.

7
oski

Vous pouvez utiliser:

SELECT 1 FROM MyTable WHERE... LIMIT 1

Utilisez select 1 pour empêcher la vérification des champs inutiles.

Utilisez LIMIT 1 pour empêcher la vérification des lignes inutiles.

6
user3059943

Autre option:

SELECT CASE
    WHEN EXISTS (
        SELECT 1
        FROM [MyTable] AS [MyRecord])
    THEN CAST(1 AS BIT) ELSE CAST(0 AS BIT)
END
0
Pranav

J'utilise cette façon:

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