Postgres conserve-t-il l'ordre d'insertion des enregistrements?


19

Par exemple, lorsque j'utilise une requête qui renvoie des ID d'enregistrement

INSERT INTO projects(name)
VALUES (name1), (name2), (name3) returning id;

Qui produisent une sortie:

1
2
3

Ces identifiants pointeront-ils vers les valeurs insérées correspondantes?

1 -> name1
2 -> name2
3 -> name3

4
La réponse réelle mise à part (ce qui, je pense, est non), vous ne devez pas vous fier à un autre ordre que celui que vous spécifiez dans vos requêtes.
dezso

Réponses:


17

La réponse pour ce cas simple est oui . Les lignes sont insérées dans l'ordre fourni dans l' VALUESexpression. Et si votre idcolonne est un serialtype, les valeurs de la séquence sous-jacente seront récupérées dans cet ordre.

Mais c'est un détail d'implémentation et il n'y a aucune garantie. En particulier, l'ordre n'est pas nécessairement maintenu dans des requêtes plus complexes avec des WHEREconditions ou des jointures.

Vous pouvez également obtenir des lacunes ou d'autres lignes mélangées si vous avez des transactions simultanées écrivant dans la même table en même temps. Peu probable, mais possible.

Il n'y a pas d'ordre "naturel" dans une table de base de données. Alors que l'ordre physique des lignes (qui se reflète dans la colonne systèmectid ) correspondra initialement à leur ordre inséré, cela peut changer à tout moment. UPDATE, DELETE, VACUUMEt d' autres commandes peuvent modifier l'ordre physique des lignes. Mais les valeurs générées pour idsont stables et ne sont en aucun cas liées à cela, bien sûr.


Je pense que Sergey faisait davantage référence à la question de savoir si la première ligne obtiendra toujours id = 1, le deuxième id = 2 et le troisième id = 3 - pas la "commande" réelle ou les lignes
a_horse_with_no_name

@a_horse_with_no_name: Pour répondre à cela : ce sera le cas avec une serialcolonne fraîchement créée - idéalement dans la même transaction.
Erwin Brandstetter

Si la question est "l'ID de name3 sera-t-il toujours plus grand que celui de name1", serait-il alors toujours correct? (En ce qui concerne votre 2ème paragraphe)
lulalala

@lulalala: Pas nécessairement pour les requêtes plus complexes avec jointures et WHEREconditions. Bien que je ne puisse pas penser à des WHEREconditions simples qui changeraient l'ordre des lignes, les jointures peuvent certainement le faire.
Erwin Brandstetter

3

La réponse d'Erwin Brandstetter peut ne pas être correcte dans certains cas.

Nous avons fait un INSERT INTO ... SELECT bar,baz FROM foo ORDER BY bar et nous voyons que cela SELECT ctid,* FROM foo montre que l'ordre physique des lignes dans le tableau ne correspond pas exactement à l'ordre d'insertion, il semble un peu brouillé. Notez que notre table a une colonne jsonb avec une taille de données très variable. La troncature expérimentale des données jsonb pendant l'insertion a rendu l'ordre d'insertion correct.


3
Comme @Erwin l'a souligné dans la première phrase , il ne dit «oui» que dans ce cas particulier mentionné dans la question. Comme l'a dit @deszo dans son commentaire , ne vous fiez jamais à l'ordre "insérer"; vous devez toujours spécifier l'ordre dans l'instruction select si vous comptez sur cet ordre pour quelque raison que ce soit.
Max Vernon
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.