Avant je n'avais pas encore essayé le code : dans le suivant je poste la version du code sql pour les deux solutions de Klaus et user457226 qui ont fonctionné sur mon ordinateur [Postgres 8.3], avec juste quelques petits ajustements pour celle de Klaus et de ma version pour celle de user457226.
Solution Klaus :
drop function IF EXISTS rebuilt_sequences() RESTRICT;
CREATE OR REPLACE FUNCTION rebuilt_sequences() RETURNS integer as
$body$
DECLARE sequencedefs RECORD; c integer ;
BEGIN
FOR sequencedefs IN Select
constraint_column_usage.table_name as tablename,
constraint_column_usage.table_name as tablename,
constraint_column_usage.column_name as columnname,
replace(replace(columns.column_default,'''::regclass)',''),'nextval(''','') as sequencename
from information_schema.constraint_column_usage, information_schema.columns
where constraint_column_usage.table_schema ='public' AND
columns.table_schema = 'public' AND columns.table_name=constraint_column_usage.table_name
AND constraint_column_usage.column_name = columns.column_name
AND columns.column_default is not null
LOOP
EXECUTE 'select max('||sequencedefs.columnname||') from ' || sequencedefs.tablename INTO c;
IF c is null THEN c = 0; END IF;
IF c is not null THEN c = c+ 1; END IF;
EXECUTE 'alter sequence ' || sequencedefs.sequencename ||' restart with ' || c;
END LOOP;
RETURN 1; END;
$body$ LANGUAGE plpgsql;
select rebuilt_sequences();
user457226 solution :
--drop function IF EXISTS reset_sequence (text,text) RESTRICT;
CREATE OR REPLACE FUNCTION "reset_sequence" (tablename text,columnname text) RETURNS bigint --"pg_catalog"."void"
AS
$body$
DECLARE seqname character varying;
c integer;
BEGIN
select tablename || '_' || columnname || '_seq' into seqname;
EXECUTE 'SELECT max("' || columnname || '") FROM "' || tablename || '"' into c;
if c is null then c = 0; end if;
c = c+1; --because of substitution of setval with "alter sequence"
--EXECUTE 'SELECT setval( "' || seqname || '", ' || cast(c as character varying) || ', false)'; DOES NOT WORK!!!
EXECUTE 'alter sequence ' || seqname ||' restart with ' || cast(c as character varying);
RETURN nextval(seqname)-1;
END;
$body$ LANGUAGE 'plpgsql';
select sequence_name, PG_CLASS.relname, PG_ATTRIBUTE.attname,
reset_sequence(PG_CLASS.relname,PG_ATTRIBUTE.attname)
from PG_CLASS
join PG_ATTRIBUTE on PG_ATTRIBUTE.attrelid = PG_CLASS.oid
join information_schema.sequences
on information_schema.sequences.sequence_name = PG_CLASS.relname || '_' || PG_ATTRIBUTE.attname || '_seq'
where sequence_schema='public';
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/