PostgreSQL: esecuzione DDL su ogni schema


8

Ho una configurazione DB multi-tenant e devo aggiungere alcune colonne. Sto usando gli schemi (e il percorso di ricerca) per partizionare i miei utenti, quindi sto cercando un modo onnipresente per applicare una modifica dello schema DDL a tutti i miei database. Inizialmente, avevo pensato che avrei potuto essere in grado di farlo come una singola query (cursore su pg_catalog), ma pensare che un'invocazione da riga di comando psql -fpotrebbe essere il modo preferito.


@RolandoMySQLDBA: Postgresinvece di PostgreSQLè perfettamente OK.
a_horse_with_no_name l'

Risposte:


11

Preferirei quest'ultima soluzione. È possibile raccogliere i nomi degli schemi in un file (uno schema per riga) 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

Quindi puoi facilmente fare quanto segue:

Avere uno script di modifica DDL (ad esempio, change_schema.sql), senza riferimento allo schema incluso

SET search_path TO :schema;

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

Quindi puoi trasformare ogni riga dell'elenco di schemi in una riga come

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

con un semplice sedcomando, ad esempio, devi solo eseguire questi comandi. Ovviamente, puoi trasformarlo in uno script di shell appropriato, se lo desideri.


1
Questo è come mi piacerebbe farlo troppo, anche se mi piacerebbe utilizzare la shell per un ciclo su lista schema, piuttosto che sed'ing esso, così ho avuto una migliore gestione degli errori. Solo per completezza, l'altro approccio sarebbe quello di scriverlo come una procedura PL / PgSQL che usava EXECUTEeseguire le istruzioni come SQL dinamico.
Craig Ringer,

9

Solo per completezza, un altro approccio è quello di eseguire il ciclo su tutti gli schemi ed eseguire la modifica con SQL dinamico in PL / PgSQL, ad esempio:

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;
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.