PostgreSQL: DDL in jedem Schema ausführen

8

Ich habe ein mandantenfähiges DB-Setup und muss einige Spalten hinzufügen. Ich verwende Schemas (und Suchpfad), um meine Benutzer zu partitionieren. Daher suche ich nach einer allgegenwärtigen Möglichkeit, eine DDL-Schemaänderung auf alle meine Datenbanken anzuwenden. Anfangs hatte ich gedacht, ich könnte es als einzelne Abfrage tun (Cursor auf pg_catalog), aber ein Befehlszeilenaufruf von psql -fkönnte der bevorzugte Weg sein.

Chris
quelle
@ RolandoMySQLDBA: Postgresstatt PostgreSQList vollkommen in Ordnung.
a_horse_with_no_name

Antworten:

11

Ich würde die letztere Lösung bevorzugen. Sie können die Schemanamen in einer Datei (ein Schema pro Zeile) sammeln in psql:

\o change_schema.sql
\t on

SELECT n.nspname
FROM pg_catalog.pg_namespace n
WHERE n.nspname !~ '^pg_' AND n.nspname <> 'information_schema';

-- reset the output
\o
\t off

Dann können Sie ganz einfach Folgendes tun:

Haben Sie ein DDL-Änderungsskript (zum Beispiel change_schema.sql) ohne Verweis auf das Inclusive-Schema

SET search_path TO :schema;

BEGIN;
...
...
ALTER TABLE orders
ADD COLUMN last_modified timestamp;
...
...
COMMIT;

Dann können Sie jede Zeile der Schemaliste in eine Zeile wie verwandeln

psql -h dbhost -d targetdb -f change_schema.sql -v schema=<schema_name>

sedZum Beispiel mit einem einfachen Befehl - dann müssen Sie nur noch diese Befehle ausführen. Natürlich können Sie es in ein richtiges Shell-Skript verwandeln, wenn Sie möchten.

dezso
quelle
1
So würde ich es auch machen, obwohl ich die Shell verwenden würde, um die Schemaliste zu durchlaufen, anstatt sie zu sedieren, also hatte ich eine bessere Fehlerbehandlung. Der Vollständigkeit halber besteht der andere Ansatz darin, es als PL / PgSQL-Prozedur zu schreiben, EXECUTEmit der die Anweisungen als dynamisches SQL ausgeführt wurden.
Craig Ringer
9

Der Vollständigkeit halber besteht ein anderer Ansatz darin, alle Schemas zu durchlaufen und die Änderung mit dynamischem SQL in PL / PgSQL auszuführen, z.

DO
$$
DECLARE
    schemaname name;
BEGIN
   FOR schemaname IN SELECT nspname FROM pg_namespace WHERE nspname NOT LIKE 'pg_%' AND nspname <> 'information_schema' LOOP
       EXECUTE format('ALTER TABLE %I.my_table ADD COLUMN blah blah;', schemaname);
   END LOOP;
END;
$$ LANGUAGE plpgsql;
Craig Ringer
quelle