Los cursores explícitos rara vez se necesitan en plpgsql. Use el cursor implícito más simple y rápido de un FOR
bucle:
Nota: Dado que los nombres de las tablas no son únicos por base de datos, debe asegurarse de que los nombres de las tablas califiquen en el esquema. Además, limito la función al esquema predeterminado 'public'. Adaptarse a sus necesidades, pero asegúrese de excluir los esquemas del sistema pg_*
y information_schema
.
Ten mucho cuidado con estas funciones. Atacan tu base de datos. Agregué un dispositivo de seguridad para niños. Comenta la RAISE NOTICE
línea y descomenta EXECUTE
para preparar la bomba ...
CREATE OR REPLACE FUNCTION f_truncate_tables(_username text)
RETURNS void AS
$func$
DECLARE
_tbl text;
_sch text;
BEGIN
FOR _sch, _tbl IN
SELECT schemaname, tablename
FROM pg_tables
WHERE tableowner = _username
AND schemaname = 'public'
LOOP
RAISE NOTICE '%',
-- EXECUTE -- dangerous, test before you execute!
format('TRUNCATE TABLE %I.%I CASCADE', _sch, _tbl);
END LOOP;
END
$func$ LANGUAGE plpgsql;
format()
requiere Postgres 9.1 o posterior. En versiones anteriores concatena la cadena de consulta de esta manera:
'TRUNCATE TABLE ' || quote_ident(_sch) || '.' || quote_ident(_tbl) || ' CASCADE';
Comando único, sin bucle
Como podemos hacer TRUNCATE
varias tablas a la vez, no necesitamos ningún cursor o bucle:
Agregue todos los nombres de tabla y ejecute una sola declaración. Más simple, más rápido:
CREATE OR REPLACE FUNCTION f_truncate_tables(_username text)
RETURNS void AS
$func$
BEGIN
RAISE NOTICE '%',
-- EXECUTE -- dangerous, test before you execute!
(SELECT 'TRUNCATE TABLE '
|| string_agg(format('%I.%I', schemaname, tablename), ', ')
|| ' CASCADE'
FROM pg_tables
WHERE tableowner = _username
AND schemaname = 'public'
);
END
$func$ LANGUAGE plpgsql;
Llamada:
SELECT truncate_tables('postgres');
Consulta refinada
Ni siquiera necesitas una función. En Postgres 9.0+ puedes ejecutar comandos dinámicos en una DO
declaración. Y en Postgres 9.5+ la sintaxis puede ser aún más simple:
DO
$func$
BEGIN
RAISE NOTICE '%',
-- EXECUTE
(SELECT 'TRUNCATE TABLE ' || string_agg(oid::regclass::text, ', ') || ' CASCADE'
FROM pg_class
WHERE relkind = 'r' -- only tables
AND relnamespace = 'public'::regnamespace
);
END
$func$;
Sobre la diferencia entre pg_class
, pg_tables
y information_schema.tables
:
Sobre regclass
y nombres de tablas citadas:
Para uso repetido
Cree una base de datos de "plantilla" (nombremos my_template
) con su estructura vainilla y todas las tablas vacías. Luego pase por un ciclo DROP
/CREATE DATABASE
:
DROP DATABASE mydb;
CREATE DATABASE mydb TEMPLATE my_template;
Esto es extremadamente rápido , porque Postgres copia toda la estructura en el nivel del archivo. No hay problemas de concurrencia u otros gastos generales que lo retrasen.
Si las conexiones concurrentes evitan que se caiga la base de datos, considere: