PL/pgSQL vérifier si une ligne existe
Je suis en train d'écrire une fonction PL/pgSQL, et je suis à la recherche de la façon la plus simple pour vérifier si une ligne existe.
Maintenant je suis en Sélectionnant un integer
dans un boolean
, qui ne fonctionne pas vraiment. Je ne suis pas expérimenté avec PL/pgSQL encore assez pour connaître la meilleure façon de le faire.
Voici une partie de ma fonction:
DECLARE person_exists boolean;
BEGIN
person_exists := FALSE;
SELECT "person_id" INTO person_exists
FROM "people" p
WHERE p.person_id = my_person_id
LIMIT 1;
IF person_exists THEN
-- Do something
END IF;
END; $$ LANGUAGE plpgsql;
Mise à jour - je suis en train de faire quelque chose comme cela pour l'instant:
DECLARE person_exists integer;
BEGIN
person_exists := 0;
SELECT count("person_id") INTO person_exists
FROM "people" p
WHERE p.person_id = my_person_id
LIMIT 1;
IF person_exists < 1 THEN
-- Do something
END IF;
Vous devez vous connecter pour publier un commentaire.
Plus simple, plus court, plus rapide:
EXISTE
.Le planificateur de requête peut s'arrêter à la première rangée trouvé - par opposition à
count()
, qui va scanner toutes les lignes correspondantes indépendamment. Fait une différence avec les grosses tables. À peine les questions avec une condition sur une colonne unique - une seule ligne se qualifie de toute façon (et il y a un index pour retrouver rapidement).Amélioration avec la participation de @a_horse_with_no_name dans les commentaires ci-dessous.
Vous pouvez même utiliser un vide
SELECT
liste:Depuis le
SELECT
liste n'est pas pertinent pour l'issue de laEXISTS
. Seule l'existence d'au moins une ligne éligible questions.count()
toujours déclenche un balayage séquentiel. EssayezEXPLAIN ANALYZE SELECT count(id) from tbl
avec n'importe quelle table. Plus sur lent de comptage dans la Postgres Wiki. Le nouvel indice de la seule analyse de Postgresql 9.2 sont censés améliorer les choses, car il peut (à condition que certaines conditions) d'utiliser un index scan pourcount(id)
, n'ont pas encore essayer et voir par moi-même ..count(*)
avec une condition (et surtout pas sur la pharmacocinétique d'une colonne) pas déclencher un balayage séquentiel.IF EXISTS
surSELECT ...; IF FOUND ...
? exemple pourif found
Simpler, shorter, faster.
True
. Ainsi, la déclaration doit êtreIF (EXISTS (SELECT FROM people WHERE person_id = my_person_id)) THEN ...
Utiliser count(*)
Modifier (pour le downvoter qui n'ont pas lu la déclaration et d'autres qui pourraient être en train de faire quelque chose de similaire)
La solution est seulement efficace, car il y a une clause where sur une colonne (et le nom de la colonne suggère que c'est la clé primaire de sorte que la clause where est très efficace)
À cause de cela
where
clause n'est pas nécessaire d'utiliser une LIMITE ou quelque chose d'autre pour tester la présence d'une ligne qui est identifié par sa clé primaire. Il est un moyen efficace de tester ça.where
condition sur la clé primaire? Je ne peux pas imaginer comment ça serait peut-être beaucoup plus lent que votre déclaration. Le plan d'exécution est à peu près identique pour les deux solutions.where
sur une colonne indexée ce est efficace.if cnt > 0
est effectivement en cours d'exécution d'une instruction select dans le fond? Et si c'est le cas ce ne serait pas le cas avec aucun solution - y compris les "inline", sélectionnez à partir de Erwin?