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.
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');
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';
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');
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:
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:
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
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.
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;
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.
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
Pour supprimer les données et conserver les structures de table dans pgAdmin , vous pouvez faire: