Tronquer toutes les tables D'une base de données Postgres

je dois régulièrement supprimer toutes les données de ma base de données PostgreSQL avant une reconstruction. Comment pourrais-je le faire directement en SQL?

pour le moment, j'ai réussi à trouver une instruction SQL qui renvoie toutes les commandes que j'ai besoin d'exécuter:

SELECT 'TRUNCATE TABLE ' ||  tablename || ';' FROM pg_tables WHERE tableowner='MYUSER';

mais je ne vois pas comment les exécuter programmatiquement une fois que je les ai.

118
demandé sur Erwin Brandstetter 2010-05-13 22:04:15

9 réponses

frustrated Withformsdesigner is correct, PL / pgSQL can do this. Voici le script:

CREATE OR REPLACE FUNCTION truncate_tables(username IN VARCHAR) RETURNS void AS $$
DECLARE
    statements CURSOR FOR
        SELECT tablename FROM pg_tables
        WHERE tableowner = username AND schemaname = 'public';
BEGIN
    FOR stmt IN statements LOOP
        EXECUTE 'TRUNCATE TABLE ' || quote_ident(stmt.tablename) || ' CASCADE;';
    END LOOP;
END;
$$ LANGUAGE plpgsql;

Cela crée une fonction stockée (vous devez le faire qu'une fois) que vous pouvez ensuite utiliser comme ceci:

SELECT truncate_tables('MYUSER');
177
répondu Henning 2017-09-02 23:25:21

les curseurs explicites sont rarement nécessaires en plpgsql. Il suffit d'utiliser le plus simple et plus rapide curseur implicite d'un FOR boucle:

Note: puisque les noms de table ne sont pas uniques par base de données, vous devez schema-qualifiez les noms de table pour être sûr. En outre, je limite la fonction au schéma par défaut 'public'. S'adapter à vos besoins, mais assurez-vous d'exclure le système schémas pg_* et information_schema .

Être très prudent avec ces fonctions. Ils nuke votre base de données. J'ai ajouté un dispositif de sécurité pour enfants. Commentaire de la RAISE NOTICE en ligne et retirez commentaires de EXECUTE pour amorcer la bombe ...

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() nécessite Postgres 9.1 ou plus. Dans les versions plus anciennes concaténer la chaîne de requête comme ceci:

'TRUNCATE TABLE ' || quote_ident(_sch) || '.' || quote_ident(_tbl)  || ' CASCADE';

Commande unique, sans boucle

puisque nous pouvons TRUNCATE plusieurs tables à la fois nous n'avons pas besoin de curseur ou de boucle du tout:

regroupe tous les noms de table et exécute une instruction unique. Plus simple, plus rapide:

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;

appel:

SELECT truncate_tables('postgres');

requête raffinée

Vous n'avez même pas besoin d'une fonction. Dans Postgres 9.0+ vous pouvez exécuter des commandes dynamiques dans DO déclaration. Et dans Postgres 9.5+ la syntaxe peut être encore plus 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$;

à propos de la différence entre pg_class , pg_tables et information_schema.tables :

à Propos de regclass et a cité les noms de table:

pour usage répété

il pourrait être plus simple et (beaucoup) plus rapide de créer un" modèle "de base de données (appelons-le my_template ) avec votre structure vanille et toutes les tables vides. Ensuite, passez par a DROP / CREATE DATABASE cycle:

DROP DATABASE mydb;
CREATE DATABASE mydb TEMPLATE my_template;

C'est extrêmement fast , parce que Postgres copie toute la structure au niveau du fichier. Pas de problèmes de concurrence ou de frais généraux qui vous ralentissent.

65
répondu Erwin Brandstetter 2018-08-02 11:03:37

si je dois faire cela, je vais simplement créer un schéma sql de db courante, puis drop & create db, puis Charger db avec le schéma sql.

ci-dessous les étapes à suivre:

1) Créer un dump Schema de la base de données ( --schema-only )

pg_dump mydb -s > schema.sql

2) la suppression de la base de données

drop database mydb;

3) Créer Une Base De Données

create database mydb;

4) Schéma D'Importation

psql mydb < schema.sql

24
répondu Sandip Ransing 2016-11-14 10:59:51

dans ce cas, il serait probablement préférable d'avoir juste une base de données vide que vous utilisez comme un modèle et quand vous avez besoin de rafraîchir, laisser tomber la base de données existante et en créer une nouvelle à partir du modèle.

7
répondu Scott Bailey 2010-05-13 20:35:44

pourriez-vous utiliser dynamic SQL pour exécuter chaque instruction à tour de rôle? Vous devrez probablement écrire un script PL/pgSQL pour le faire.

http://www.postgresql.org/docs/8.3/static/plpgsql-statements.html (section 38.5.4. L'Exécution Dynamique Commandes)

2
répondu FrustratedWithFormsDesigner 2010-05-13 18:29:44

vous pouvez le faire avec bash aussi:

#!/bin/bash
PGPASSWORD='' psql -h 127.0.0.1 -Upostgres sng --tuples-only --command "SELECT 'TRUNCATE TABLE ' || schemaname || '.' ||  tablename || ';' FROM pg_tables WHERE schemaname in ('cms_test', 'ids_test', 'logs_test', 'sps_test');" | 
tr "\n" " " | 
xargs -I{} psql -h 127.0.0.1 -Upostgres sng --command "{}"

vous aurez besoin d'ajuster les noms de schéma, les mots de passe et les noms d'utilisateur pour correspondre à vos schémas.

1
répondu simao 2013-04-09 13:56:53

pour supprimer les données et préserver la table-structures dans pgAdmin vous pouvez faire:

  • clic droit sur la base de données- > sauvegarde, sélectionnez "schéma seulement"
  • supprimer la base de données
  • créer une nouvelle base de données et l'appeler comme l'ancien
  • faites un clic droit sur la nouvelle base de données- > restaurer - > sélectionnez la sauvegarde, sélectionnez "schéma seulement"
0
répondu mYnDstrEAm 2017-03-29 12:09:33

Nettoyage AUTO_INCREMENT version:

CREATE OR REPLACE FUNCTION truncate_tables(username IN VARCHAR) RETURNS void AS $$
DECLARE
    statements CURSOR FOR
        SELECT tablename FROM pg_tables
        WHERE tableowner = username AND schemaname = 'public';
BEGIN
    FOR stmt IN statements LOOP
        EXECUTE 'TRUNCATE TABLE ' || quote_ident(stmt.tablename) || ' CASCADE;';

        IF EXISTS (
            SELECT column_name 
            FROM information_schema.columns 
            WHERE table_name=quote_ident(stmt.tablename) and column_name='id'
        ) THEN
           EXECUTE 'ALTER SEQUENCE ' || quote_ident(stmt.tablename) || '_id_seq RESTART WITH 1';
        END IF;

    END LOOP;
END;
$$ LANGUAGE plpgsql;
0
répondu RomanGorbatko 2017-08-17 19:42:17

les Gars le mieux et propre est :

1) Créer un dump Schema de la base de données (--schema-only) pg_dump mydb -s > schéma.sql

2) la suppression de la base de données drop database mydb;

3) Créer Une Base De Données créer la base de données mydb;

4) Schéma D'Importation psql mydb < schéma.sql

Son travail pour moi!

bonne journée. Hiram Walker

0
répondu Hiram Walker 2018-06-05 15:01:10