PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

Elimina o crea database dalla procedura memorizzata in PostgreSQL

Il messaggio di errore è chiaro come il manuale su questo:

Una funzione plgpsql è circondata automaticamente da un blocco di transazione. Il lungo e il corto:non puoi farlo direttamente. C'è un motivo particolare per cui non puoi semplicemente chiamare il comando DDL?

DROP database $mydb;

puoi aggirare queste restrizioni con il modulo aggiuntivo dblink come @Igor suggerito. Devi installarlo una volta per database, quello in cui chiami le funzioni dblink, non l'altro in cui esegui i comandi.
Ti permette di scrivere una funzione usando dblink_exec() così:

CREATE OR REPLACE FUNCTION f_drop_db(text)
  RETURNS text LANGUAGE sql AS
$func$
SELECT dblink_exec('port=5432 dbname=postgres'
                  ,'DROP DATABASE ' || quote_ident($1))
$func$;

quote_ident() previene la possibile SQL injection.

Chiama:

SELECT f_drop_db('mydb');

In caso di successo vedi:

La stringa di connessione potrebbe anche puntare allo stesso db in cui viene eseguita la sessione. Il comando viene eseguito all'esterno di un blocco di transazione, il che ha due conseguenze:

  • Non è possibile eseguire il rollback.
  • Ti permette di chiamare DROP DATABASE "tramite un proxy" dall'interno di una funzione.

Potresti creare un FOREIGN DATA WRAPPER e un FOREIGN SERVER per memorizzare una connessione e semplificare la chiamata:

CREATE FOREIGN DATA WRAPPER postgresql VALIDATOR postgresql_fdw_validator;

CREATE SERVER your_fdw_name_here FOREIGN DATA WRAPPER postgresql
OPTIONS (hostaddr '12.34.56.78', port '5432', dbname 'postgres');

Utilizzo del db di manutenzione predefinito postgres , che sarebbe una scelta ovvia. Ma qualsiasi db è possibile.

Funzione semplificata che ne fa uso:

CREATE OR REPLACE FUNCTION f_drop_db(text)
  RETURNS text LANGUAGE sql AS
$func$
SELECT dblink_exec('your_fdw_name_here', 'DROP DATABASE ' || quote_ident($1))
$func$;