viernes, 28 de marzo de 2014

Actualizar Secuencias en POSTGRESQL



En estos días estuve trabajando con una base de datos en PostgreSQL en su versión 9.1, Normalmente mientras hacemos pruebas insertamos registros en la BD y las secuencias que están amarradas a los pk de las tablas (si es que estas trabajando con secuencias) no se actualizan automáticamente después de hacer un TRUNCATE, por lo que pensé  en crear una función en la BD que permita hacer tal labor aquí se las dejo les puede servir.

Esta primera función me devuelve el máximo id de la tabla en consulta:
 
CREATE OR REPLACE FUNCTION obtenermaxid(intabla character varying)
  RETURNS SETOF record AS
$BODY$
DECLARE SQL text;
BEGIN
    SQL := 'SELECT MAX('||intabla||'_id) FROM '||intabla;
    RETURN QUERY EXECUTE SQL;
END
$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100
  ROWS 1000;

Esta segunda función se encarga de actualizar las secuencias mandándole el nombre de la tabla y el valor a actualizar:
 
CREATE OR REPLACE FUNCTION iudsecuencias(intabla character varying, valor integer)
  RETURNS SETOF record AS
$BODY$
DECLARE SQL text;
BEGIN
                SQL := 'SELECT setval('''||intabla||'_seq'||''','||valor||',''t'')';
                RETURN QUERY EXECUTE SQL;
END
$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100
  ROWS 1000;

Finalmente esta ultima es la que se ejecuta cada vez que se quiere actualizar las secuencias

CREATE OR REPLACE FUNCTION actualizarsecuencias()
  RETURNS boolean AS
$BODY$
DECLARE nombretabla character varying; maxid integer;
cursor_tablas cursor
for SELECT tablename FROM pg_tables WHERE schemaname = 'public';
BEGIN

                OPEN cursor_tablas;
                LOOP
                FETCH cursor_tablas into nombretabla;
                EXIT WHEN NOT FOUND;
                               maxid  := (select id from obtenermaxid(nombretabla) as ("id" integer));
                               IF maxid IS NULL THEN
                                               perform (select * from iudsecuencias(nombretabla,1) as ("r" bigint));
                               ELSE
                                               perform (select * from iudsecuencias(nombretabla,maxid) as ("r" bigint));
                               END IF;
                END LOOP;
                CLOSE cursor_tablas;
                return true;
END
$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100;

Esta se encarga de consultar todas las tablas en nuestra BD y guardarlas en un cursor para después recorrer el cursor e ir actualizando secuencia por secuencia; cabe mencionar que yo manejo un estándar de nomenclatura para las tablas y las secuencias de la BD; por ejemplo mi tabla persona se llamaría tb_persona y su secuencia se llamaría tb_persona_seq... espero les sirva  Dios los Bendiga