martes, 22 de mayo de 2018

Restablecer las secuencias ID en la base de datos postgresql

Normalmente después de restablecer la base de datos las secuencias de id se pierden provocando errores al momento de escribir en la base de datos. Para corregir todos estos errores cree el siguiente script el cual se ejecuta en la base de datos con esquema publico y agrega tablas a excluir. Ademas dejo dos scripts simples con los cuales comprobar si se corrige el problema.

--Corregir secuencias de id luego de restaurar
DO
$$
DECLARE
v_table VARCHAR;
v_table_cp VARCHAR;
v_table_block VARCHAR;
v_sql_string VARCHAR;
v_exclude_table VARCHAR[] := ARRAY['spatial_ref_sys', 'geometry_columns'];
v_include_table VARCHAR[];
v_i INTEGER;
v_num INTEGER;
v_max INTEGER;
v_next INTEGER;

BEGIN
SELECT INTO v_num count(relname)
FROM pg_class c
JOIN pg_namespace nsp ON c.relnamespace = nsp.oid
WHERE c.relname <> ALL(v_exclude_table) AND
nsp.nspname = 'public'
AND relhasindex = 't';

v_include_table := ARRAY(SELECT c.relname
FROM pg_class c
JOIN pg_namespace nsp ON c.relnamespace = nsp.oid
WHERE c.relname <> ALL(v_exclude_table) AND
nsp.nspname = 'public'
AND relhasindex = 't');

FOR v_i IN 1..v_num
LOOP

BEGIN
v_table := 'SELECT MAX(id) FROM ' || v_include_table[v_i];
EXECUTE v_table INTO v_max;

-- Then run...
-- This should be higher than the last result.
v_table_cp := 'SELECT nextval(''' || v_include_table[v_i] ||'_id_seq'')'; -- || ') INTO v_next';
EXECUTE v_table_cp INTO v_next;

-- If it's not higher... run this set the sequence last to your highest id.
-- (wise to run a quick pg_dump first...)
IF (v_next < v_max) THEN

-- protect against concurrent inserts while you update the counter
v_table_block := 'LOCK TABLE '|| v_include_table[v_i] ||' IN EXCLUSIVE MODE';
EXECUTE v_table_block;
-- Update the sequence
v_sql_string := 'SELECT setval('''|| v_include_table[v_i] || '_id_seq'', COALESCE((SELECT MAX(id)+1 FROM ' || v_include_table[v_i] || '), 1), false)';

EXECUTE v_sql_string;
RAISE NOTICE 'Table %s correct sequence',v_include_table[v_i];
END IF;
EXCEPTION WHEN others THEN
RAISE NOTICE 'Table %s ignore',v_include_table[v_i];
END;

END LOOP;
END
$$
--Para validar cambie tabla por el nombre de la tabla en ambos scripts sql
ultimo id de base de datos para la tabla
--SELECT MAX(id) FROM tabla
id que se genera al insertar un nuevo registro
--SELECT nextval('tabla_id_seq')

No hay comentarios:

Publicar un comentario