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?
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.
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
Vous pouvez utiliser:
SELECT 1 FROM MyTable WHERE <MyCondition>
Si aucun enregistrement ne correspond à la condition, le jeu d'enregistrements obtenu est vide.
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.
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 nullesCOUNT(column name)
comptera seulement occurrences non nulles du nom de la colonneSELECT 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.
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.
Autre option:
SELECT CASE
WHEN EXISTS (
SELECT 1
FROM [MyTable] AS [MyRecord])
THEN CAST(1 AS BIT) ELSE CAST(0 AS BIT)
END
J'utilise cette façon:
IIF(EXISTS (SELECT TOP 1 1
FROM Users
WHERE FirstName = 'John'), 1, 0) AS DoesJohnExist