PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

Solte ou crie banco de dados do procedimento armazenado no PostgreSQL


A mensagem de erro é tão clara quanto o manual nisto:

Uma função plgpsql é cercada por um bloco de transação automaticamente. Em resumo:você não pode fazer isso - diretamente. Existe uma razão específica para que você não possa simplesmente chamar o comando DDL?
DROP database $mydb;

Você pode contornar essas restrições com o módulo adicional dblink como @Igor sugerido. Você precisa instalá-lo uma vez por banco de dados - aquele em que você chama as funções dblink, não a (outra) em que você executa comandos.
Permite que você escreva uma função usando dblink_exec() assim:
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() impede possível injeção de SQL.

Ligar:
SELECT f_drop_db('mydb');

Sobre o sucesso você vê:

A string de conexão pode até apontar para o mesmo banco de dados em que sua sessão é executada. O comando é executado fora de um bloco de transação, o que tem duas consequências:
  • Não pode ser revertido.
  • Permite que você chame DROP DATABASE "por meio de um proxy" de dentro de uma função.

Você pode criar um FOREIGN DATA WRAPPER e um FOREIGN SERVER para armazenar uma conexão e simplificar a chamada:
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');

Usando o banco de dados de manutenção padrão postgres , o que seria uma escolha óbvia. Mas qualquer db é possível.

Função simplificada fazendo uso disso:
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$;