web-dev-qa-db-fra.com

Vérification la plus rapide si la ligne existe dans PostgreSQL

J'ai un tas de lignes que je dois insérer dans la table, mais ces insertions sont toujours effectuées par lots. Je veux donc vérifier si une seule ligne du lot existe dans la table car je sais qu’elles ont toutes été insérées.

Donc, ce n'est pas une vérification de clé primaire, mais ne devrait pas avoir trop d'importance. Je voudrais seulement vérifier une seule ligne pour que count(*) ne soit probablement pas bon, alors c'est quelque chose comme exists je suppose.

Mais comme je suis assez nouveau pour PostgreSQL, je préférerais demander à ceux qui savent.

Mon lot contient des lignes avec la structure suivante:

userid | rightid | remaining_count

Donc, si la table contient des lignes avec userid fourni, cela signifie qu'elles y sont toutes présentes.

140
Valentin Kuzub

Utilisez la clé EXISTS Word pour un retour VRAI/FAUX:

select exists(select 1 from contact where id=12)
261
MikeM

Que diriez-vous simplement:

select 1 from tbl where userid = 123 limit 1;

123 est l'ID utilisateur du lot que vous êtes sur le point d'insérer.

La requête ci-dessus renvoie soit un ensemble vide, soit une seule ligne, selon qu'il existe ou non des enregistrements avec l'ID utilisateur indiqué.

Si cela s'avère trop lent, vous pouvez envisager de créer un index sur tbl.userid.

si même une seule ligne de lot existe dans la table, dans ce cas, je n'ai pas à insérer mes lignes car je sais qu'elles ont toutes été insérées.

Pour que cela reste vrai même si votre programme est interrompu en cours de lot, nous vous recommandons de vous assurer de gérer les transactions de base de données correctement (c'est-à-dire que l'intégralité du lot est insérée dans une seule transaction).

32
NPE
INSERT INTO target( userid, rightid, count )
  SELECT userid, rightid, count 
  FROM batch
  WHERE NOT EXISTS (
    SELECT * FROM target t2, batch b2
    WHERE t2.userid = b2.userid
    -- ... other keyfields ...
    )       
    ;

BTW: si vous voulez le tout le lot échoue en cas de duplication, alors (avec une contrainte de clé primaire)

INSERT INTO target( userid, rightid, count )
SELECT userid, rightid, count 
FROM batch
    ;

fera exactement ce que vous voulez: soit cela réussit, soit cela échoue.

9
wildplasser
select true from tablename where condition limit 1;

Je crois que c’est la requête que postgres utilise pour vérifier les clés étrangères.

Dans votre cas, vous pouvez le faire en une fois aussi:

insert into yourtable select $userid, $rightid, $count where not (select true from yourtable where userid = $userid limit 1);
1
Royce

Règle de base

select existe (sélectionnez true parmi xx où xx) en tant que "Est-ce que 1 + 1 ajoute jusqu'à 2";

0
CodeFarmer

comme l'a souligné @MikeM.

select exists(select 1 from contact where id=12)

avec index au contact, cela permet généralement de réduire le coût en temps à 1 ms.

CREATE INDEX index_contact on contact(id);
0
hcnak

Si vous pensez à la performance, vous pouvez peut-être utiliser "PERFORM" dans une fonction comme celle-ci:

 PERFORM 1 FROM skytf.test_2 WHERE id=i LIMIT 1;
  IF FOUND THEN
      RAISE NOTICE ' found record id=%', i;  
  ELSE
      RAISE NOTICE ' not found record id=%', i;  
 END IF;
0
francs
SELECT 1 FROM user_right where userid = ? LIMIT 1

Si votre jeu de résultats contient une ligne, vous n'avez pas à l'insérer. Sinon, insérez vos enregistrements.

0
Fabian Barney