2017-10-16 19 views
1

Je vais donner un exemple simplifié de mon problème. J'ai deux tables: reviews et users.Est-ce la manière correcte d'insérer INSERT ON CONFLICT dans Postgres?

reviews est mis à jour avec un tas de commentaires que les utilisateurs publient. Le processus qui récupère les avis renvoie également des informations pour l'utilisateur qui l'a soumis (et certaines données utilisateur changent fréquemment).

Je veux mettre à jour users chaque fois que je mets à jour reviews, en vrac, en utilisant COPY. Le problème se pose pour users lorsque les données récupérées contient deux ou plusieurs avis du même utilisateur. Si je fais un simple INSERT ON CONFLICT, je pourrais se retrouver avec des erreurs depuis et INSERT instruction ne peut pas mettre à jour la même ligne deux fois. Un SELECT DISTINCT résoudrait ce problème, mais je veux également garantir que j'insère les dernières données dans la table users. C'est comme ça que je le fais. Gardez à l'esprit que je le fais en vrac:

1. Créez une table temporaire afin que nous puissions COPY à partir de/à partir de ce.

CREATE TEMPORARY TABLE users_temp (
    id uuid, 
    stat_1 integer, 
    stat_2 integer, 
    account_age_in_mins integer); 

2. COPY données dans la table temporaire

COPY users_temp (
    id, 
    stat_1, 
    stat_2, 
    account_age_in_mins) FROM STDIN CSV ENCODING 'utf-8'; 

3. Table de verrouillage users et effectuer INSERT ON CONFLICT

LOCK TABLE users in EXCLUSIVE MODE; 

INSERT INTO users SELECT DISTINCT ON (1) 
    users_temp.id, 
    users_temp.stat_1, 
    users_temp.stat_2, 
    users_temp.account_age_in_mins 
FROM users_temp 
ORDER BY 1, 4 DESC, 2, 3 
ON CONFLICT (id) DO UPDATE 
SET 
    stat_1 = EXCLUDED.stat_1, 
    stat_2 = EXCLUDED.stat_2, 
    account_age_in_mins = EXCLUDED.account_age_in_mins'; 

La raison pour laquelle je fais un SELECT DISTINCT et un ORDER BY à l'étape 3) est parce que je:

  1. veux seulement retourner une instance des lignes en double.
  2. À partir de ces duplicates assurez-vous que je reçois l'enregistrement le plus à jour par en triant sur le account_age_in_mins.

Est-ce la bonne méthode pour atteindre mon objectif?

+0

Ça a l'air plutôt bien. –

+0

@LaurenzAlbe Bon à entendre. Tout ce que tu ferais différemment? – Petar

+0

À première vue, non. –

Répondre