web-dev-qa-db-fra.com

Tronquer toutes les tables dans une base de données Postgres

J'ai régulièrement besoin de supprimer toutes les données de ma base de données PostgreSQL avant une reconstruction. Comment pourrais-je le faire directement dans SQL?

Pour le moment, j'ai réussi à créer une instruction SQL qui renvoie toutes les commandes que je dois exécuter:

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

Mais je ne vois pas comment les exécuter par programme une fois que je les aurai.

137
Sig

FrustratedWithFormsDesigner est correct, PL/pgSQL peut le faire. 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 une seule fois) que vous pouvez ensuite utiliser comme ceci:

SELECT truncate_tables('MYUSER');
198
Henning

Les curseurs explicites sont rarement nécessaires dans plpgsql. Utilisez le plus simple et le plus rapide curseur implicite d'une boucle FOR :

Note: Comme les noms de table ne sont pas uniques par base de données, vous devez qualifier les noms de table par schéma pour en être sûr. De plus, je limite la fonction au schéma par défaut 'public'. Adaptez-vous à vos besoins, mais veillez à exclure les schémas système pg_* Et information_schema.

Soyez très prudent ​​avec ces fonctions. Ils détruisent votre base de données. J'ai ajouté un dispositif de sécurité pour enfants. Commentez la ligne RAISE NOTICE Et décommentez 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() requiert Postgres 9.1 ou une version ultérieure. 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, pas de boucle

Puisque nous pouvons TRUNCATE plusieurs tables à la fois, nous n’avons besoin ni de curseur ni de boucle:

Agrégez tous les noms de table et exécutez une seule instruction. 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 une instruction DO . 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 des noms de tables cités:

Pour un usage répété

Créez une base de données "template" (appelons-la my_template) Avec votre structure Vanilla et toutes les tables vides. Puis passez à travers le DROP/ CREATE DATABASE cycle:

DROP DATABASE mydb;
CREATE DATABASE mydb TEMPLATE my_template;

C'est extrêmement rapide, car Postgres copie toute la structure au niveau du fichier. Aucun problème de concurrence ou autre surcharge ne vous ralentit.

Si des connexions simultanées vous empêchent de supprimer la base de données, tenez compte des points suivants:

82
Erwin Brandstetter

Si je dois faire cela, je créerai simplement un schéma SQL de la base de données actuelle, puis déposerai et créer une base de données, puis chargerai la base de données avec le schéma SQL.

Voici les étapes à suivre:

1) Créer un dump de schéma de base de données (--schema-only)

pg_dump mydb -s > schema.sql

2) Supprimer 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

33
Sandip Ransing

Dans ce cas, il serait probablement préférable de simplement utiliser une base de données vide que vous utilisez comme modèle et, lorsque vous devez l'actualiser, supprimez la base de données existante et créez-en une nouvelle à partir du modèle.

9
Scott Bailey

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;
3
RomanGorbatko

Pourriez-vous utiliser du SQL dynamique pour exécuter chaque instruction à son tour? Pour ce faire, vous devrez probablement écrire un script PL/pgSQL.

http://www.postgresql.org/docs/8.3/static/plpgsql-statements.html (section 38.5.4. Exécution de commandes dynamiques)

Vous pouvez aussi le faire avec bash:

#!/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 devrez ajuster les noms de schéma, les mots de passe et les noms d'utilisateur afin qu'ils correspondent à vos schémas.

3
simao

Les gars le meilleur et le moyen propre est de:

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

2) Déposer la base de données déposer la base de données mydb;

3) Créer une base de données créer une base de données mydb;

4) Importer le schéma psql mydb <schema.sql

C'est un travail pour moi!

Bonne journée. Hiram Walker

2
Hiram Walker

Pour supprimer les données et conserver les structures de table dans pgAdmin , vous pouvez faire:

  • Cliquez avec le bouton droit sur la base de données -> sauvegarde, sélectionnez "Schéma uniquement".
  • Déposer la base de données
  • Créez une nouvelle base de données et nommez-la comme l'ancien
  • Cliquez avec le bouton droit sur la nouvelle base de données -> restaurer -> sélectionnez la sauvegarde, sélectionnez "Schéma uniquement".
2
mYnDstrEAm