Vous n'êtes pas identifié(e).
Pages : 1
Bonjour
J'ai une table avec une clé primaire "id" de type integer
A la suite d'un insert pour intégrer de nouvelles entités dans ma table
Je souhaiterai réorganiser les clés primaire selon un des champs
Par exemple soit une table "table"
id | Nom
1 ZZZ
2 ABA
Et une autre table à intégrer dans la "table"
id | Nom
1 AAA
2 ACA
Actuellement j'ai la ligne ZZZ qui a pour clé primaire 1
et l'entité AAA venant d'être intégré a pour clé 3
Quel code permet ceci :
id | Nom
1 AAA
2 ABA
3 ACA
4 ZZZ
J'ai essayé d'écraser les clés primaires via
UPDATE table SET id= rank
FROM (SELECT rank() over (order by Nom) as rank FROM table)
mais "La clé primaire 1 ne peut être dupliquée"
Merci de votre aide
Hors ligne
Bonjour,
Pour quelle raison pensez-vous qu'une réorganisation des valeurs d'une clé technique a un intérêt ? Même si vous le faites maintenant il est fort probable que les lignes vont continuer à avoir des valeurs dans le désordre, et essayer de maintenir un ordre quelconque sera à peu près impossible, sans compter sur les impacts tels que les clé étrangères.
La solution habituelle est d'utiliser une colonne définie comme GENERATED ALWAYS AS IDENTITY (ou serial/bigserial pour les versions plus anciennes), et ne pas assigner de valeur explicite pour la clé technique.
Julien.
https://rjuju.github.io/
Hors ligne
La redistribution de la clef primaire échoue via l'UPDATE du fait que Postgres ne teste pas l'unicité à la fin de l'instruction, comme indiqué ici dans la doc:
https://doc.postgresql.fr/14/sql-set-constraints.html
De plus, PostgreSQL vérifie les contraintes uniques non déferrables immédiatement, pas à la fin de l'instruction comme le standard le suggère.
Pour que l'UPDATE passe, il faudrait que la contrainte soit DEFERRABLE INITIALLY DEFERRED ou DEFERRABLE tout court et que la transaction la passe en DEFERRED.
L'autre solution est de ne pas faire un UPDATE mais de réinsérer les lignes avec DELETE+INSERT:
with d as (delete from table returning *)
insert into table select row_number() over (order by Nom), Nom from d;
Je suggère row_number() au lieu de rank() parce que rank() créé des doublons en cas d'égalité
Dernière modification par dverite (14/10/2022 20:25:38)
@DanielVerite
http://blog-postgresql.verite.pro/
Hors ligne
Pages : 1