Ces fonctions présentent de nombreux dangers lorsque les noms de séquence, de colonne, de table ou de schéma comportent des caractères bizarres tels que des espaces, des signes de ponctuation, etc. J'ai écrit ceci :
CREATE OR REPLACE FUNCTION sequence_max_value(oid) RETURNS bigint
VOLATILE STRICT LANGUAGE plpgsql AS $$
DECLARE
tabrelid oid;
colname name;
r record;
newmax bigint;
BEGIN
FOR tabrelid, colname IN SELECT attrelid, attname
FROM pg_attribute
WHERE (attrelid, attnum) IN (
SELECT adrelid::regclass,adnum
FROM pg_attrdef
WHERE oid IN (SELECT objid
FROM pg_depend
WHERE refobjid = $1
AND classid = 'pg_attrdef'::regclass
)
) LOOP
FOR r IN EXECUTE 'SELECT max(' || quote_ident(colname) || ') FROM ' || tabrelid::regclass LOOP
IF newmax IS NULL OR r.max > newmax THEN
newmax := r.max;
END IF;
END LOOP;
END LOOP;
RETURN newmax;
END; $$ ;
Vous pouvez l'appeler pour une seule séquence en lui passant l'OID et il renverra le numéro le plus élevé utilisé par toute table qui a la séquence par défaut ; ou vous pouvez l'exécuter avec une requête comme celle-ci, pour réinitialiser toutes les séquences dans votre base de données :
select relname, setval(oid, sequence_max_value(oid))
from pg_class
where relkind = 'S';
En utilisant un qual différent, vous pouvez réinitialiser uniquement la séquence dans un certain schéma, et ainsi de suite. Par exemple, si vous voulez ajuster les séquences dans le schéma "public" :
select relname, setval(pg_class.oid, sequence_max_value(pg_class.oid))
from pg_class, pg_namespace
where pg_class.relnamespace = pg_namespace.oid and
nspname = 'public' and
relkind = 'S';
Notez qu'en raison du fonctionnement de setval(), vous n'avez pas besoin d'ajouter 1 au résultat.
En guise de conclusion, je dois vous avertir que certaines bases de données semblent avoir des liens par défaut avec les séquences d'une manière qui ne permet pas aux catalogues du système d'en avoir une information complète. Cela se produit lorsque vous voyez des choses comme ceci dans le fichier psql's \d :
alvherre=# \d baz
Tabla «public.baz»
Columna | Tipo | Modificadores
---------+---------+------------------------------------------------
a | integer | default nextval(('foo_a_seq'::text)::regclass)
Notez que l'appel nextval() dans cette clause par défaut a un cast ::text en plus du cast ::regclass. I pensez à Ceci est dû au fait que les bases de données sont pg_dumpées à partir d'anciennes versions de PostgreSQL. Ce qui se passe, c'est que la fonction sequence_max_value() ci-dessus ignorera une telle table. Pour résoudre le problème, vous pouvez redéfinir la clause DEFAULT pour faire référence à la séquence directement sans le cast :
alvherre=# alter table baz alter a set default nextval('foo_a_seq');
ALTER TABLE
Ensuite, psql l'affiche correctement :
alvherre=# \d baz
Tabla «public.baz»
Columna | Tipo | Modificadores
---------+---------+----------------------------------------
a | integer | default nextval('foo_a_seq'::regclass)
Dès que vous avez corrigé cela, la fonction fonctionne correctement pour cette table ainsi que pour toutes les autres qui pourraient utiliser la même séquence.
1 votes
Je suis curieux est-ce que vous laissez tomber la base de données avant de faire une restauration ? Je me souviens vaguement que cela s'est produit, mais je peux me tromper :P
39 votes
Le wiki de PostgreSQL a une page sur Correction des séquences .
26 votes
Juste pour aider à la googlelisation, le message d'erreur envoyé ici est : "La valeur de la clé dupliquée viole la contrainte d'unicité..."
5 votes
Voici comment sqlsequencereset dans Django le fait : SELECT setval(pg_get_serial_sequence("<nom_table>", 'id'), coalesce(max("id"), 1), max("id") IS NOT null) FROM "<nom_table>" ;
1 votes
La première instance du <nom de la table> doit être entourée de guillemets simples pour que la fonction pg_get_serioal_sequence fonctionne : SELECT setval(pg_get_serioal_sequence('<nom_table>', 'id'), coalesce(max("id"), 1), max("id") IS NOT null) FROM "<nom_table>"
0 votes
Question connexe : stackoverflow.com/questions/62059947/
0 votes
stackoverflow.com/questions/244243/