POSTGRES - empêche l'incrémentation en série avec ON CONFLICT DO NOTHING [duplicate]

Sep 03 2020

duplicata de cette question

Disons que j'ai le tableau suivant. Je veux des noms uniques dans le tableau afin qu'il n'y ait pas de doublons. Le processus qui insère un objet ne devrait pas avoir besoin de vérifier si un objet portant ce nom est déjà présent.

CREATE TABLE things(
    id SMALLSERIAL PRIMARY KEY,
    name varchar UNIQUE
);

Lorsque j'insère des valeurs comme celle-ci, cela fonctionne. Si «desk» est déjà dans les choses, il ne sera pas inséré.

INSERT INTO things (name)
VALUES ('desk')
ON CONFLICT DO NOTHING;

Le seul problème est ON CONFLICT NE RIEN ne fait vraiment rien. Il incrémente toujours la séquence du champ id.

Si cela se produit trop souvent, la séquence d'identifiants finit par devenir trop grande pour le type de champ.

Y a-t-il un moyen d'empêcher que cela se produise?

Réponses

4 GMB Sep 03 2020 at 16:08

En utilisant insert ... on conflict, vous ne pouvez pas empêcher l' serialincrémentation automatique en cas de conflit. Postgres (tout comme les autres bases de données) ne garantit pas que les séries soient séquentielles, comme expliqué dans la documentation :

Parce que smallserial, serialet bigserialsont implémentés à l'aide de séquences, il peut y avoir des «trous» ou des lacunes dans la séquence de valeurs qui apparaît dans la colonne, même si aucune ligne n'est jamais supprimée. Une valeur allouée à partir de la séquence est toujours «épuisée» même si une ligne contenant cette valeur n'est jamais correctement insérée dans la colonne du tableau. Cela peut se produire, par exemple, si la transaction d'insertion est annulée.

Si vous en exécutez beaucoup insertqui finissent en conflit, une façon de limiter le bleading serait de changer la syntaxe en not exists:

insert into things (name)
select name
from (values ('desk')) v(name)
where not exists (select 1 from things t1 where t1.name = v.name)

Notez que cela ne garantit toujours pas que les publications en série seront séquentielles (reportez-vous à la citation ci-dessus de la documentation).