« POSTGRES Vérifier les séquences d'un schéma » : différence entre les versions
Aller à la navigation
Aller à la recherche
sequences postgres |
mAucun résumé des modifications |
||
| Ligne 60 : | Ligne 60 : | ||
</syntaxhighlight>C'est ''copilot'' qui est arrivé à pondre ça après 4 ou 5 essais infructueux. | </syntaxhighlight>C'est ''copilot'' qui est arrivé à pondre ça après 4 ou 5 essais infructueux. | ||
Le résultat est quelque chose comme :<syntaxhighlight lang="text"> | On appelle la fonction avec :<syntaxhighlight lang="postgresql"> | ||
SELECT * FROM check_sequences('monschema'); | |||
</syntaxhighlight>Le résultat est quelque chose comme :<syntaxhighlight lang="text"> | |||
user_role id user_role_id_seq 1 2 NOK | user_role id user_role_id_seq 1 2 NOK | ||
user_list id prd_user_list_id_seq 382 382 OK | user_list id prd_user_list_id_seq 382 382 OK | ||
| Ligne 81 : | Ligne 84 : | ||
application id prd_application_id_seq 93 93 OK | application id prd_application_id_seq 93 93 OK | ||
status_value id prd_status_value_id_seq 11 11 OK | status_value id prd_status_value_id_seq 11 11 OK | ||
</syntaxhighlight> | </syntaxhighlight>On pourait envisager un script qui fasse les mises à jours automatiquement... à voir. | ||
Dernière version du 27 janvier 2026 à 16:19
Souvent on a des "inserts" dans une base qui plantent à cause de la contrainte d'unicité d'une table. Plus particulièrement quand on a un id que dépends d'une séquence.
On utilise pour cela la fonction suivante :
CREATE OR REPLACE FUNCTION check_sequences(p_schema text)
RETURNS TABLE(
table_name text,
column_name text,
sequence_name text,
seq_value bigint,
max_value bigint,
status text
)
LANGUAGE plpgsql
AS $$
DECLARE
rec record;
dyn_sql text;
max_val bigint;
last_val bigint;
BEGIN
FOR rec IN
SELECT
t.relname AS table_name,
a.attname AS column_name,
s.relname AS sequence_name,
n.nspname AS seq_schema
FROM pg_class t
JOIN pg_namespace n2 ON n2.oid = t.relnamespace
JOIN pg_attribute a ON a.attrelid = t.oid
JOIN pg_attrdef ad ON ad.adrelid = t.oid AND ad.adnum = a.attnum
JOIN pg_depend d ON d.refobjid = t.oid AND d.refobjsubid = a.attnum
JOIN pg_class s ON s.oid = d.objid AND s.relkind = 'S'
JOIN pg_namespace n ON n.oid = s.relnamespace
WHERE t.relkind = 'r'
AND n2.nspname = p_schema
LOOP
-- Lire last_value de la séquence
EXECUTE format('SELECT last_value FROM %I.%I', rec.seq_schema, rec.sequence_name)
INTO last_val;
-- Lire MAX(colonne) de la table
dyn_sql := format(
'SELECT COALESCE(MAX(%I), 0) FROM %I.%I',
rec.column_name, p_schema, rec.table_name
);
EXECUTE dyn_sql INTO max_val;
-- Assigner aux OUT
table_name := rec.table_name;
column_name := rec.column_name;
sequence_name := rec.sequence_name;
seq_value := last_val;
max_value := max_val;
status := CASE WHEN last_val < max_val THEN 'NOK' ELSE 'OK' END;
RETURN NEXT;
END LOOP;
END;
$$;
C'est copilot qui est arrivé à pondre ça après 4 ou 5 essais infructueux. On appelle la fonction avec :
SELECT * FROM check_sequences('monschema');
Le résultat est quelque chose comme :
user_role id user_role_id_seq 1 2 NOK
user_list id prd_user_list_id_seq 382 382 OK
user_alert id user_alert_id_seq 7 7 OK
application id prd_application_id_seq 93 93 OK
status_value id prd_status_value_id_seq 10 11 NOK
Tous les NOK (not OK) indiquent une séquence pas à jours. On fait les mises à jour:
ALTER SEQUENCE spoc_rec.user_role_id_seq
RESTART 2;
ALTER SEQUENCE prd_status_value_id_seq
RESTART 11;
Tout revient dans l'ordre:
user_role id user_role_id_seq 2 2 OK
user_spoc id prd_user_spoc_id_seq 382 382 OK
user_alert id user_alert_id_seq 7 7 OK
application id prd_application_id_seq 93 93 OK
status_value id prd_status_value_id_seq 11 11 OK
On pourait envisager un script qui fasse les mises à jours automatiquement... à voir.