postgre创建存储过程_在PostgreSQL中从存储过程删除或创建数据库

在PostgreSQL中,由于`DROP DATABASE`不能在事务块内执行,因此直接在函数或存储过程中删除数据库会遇到错误。解决这个问题的一种方法是使用额外的模块`dblink`。通过创建一个使用`dblink_exec()`的函数,可以绕过这个限制,实现从函数外部执行`DROP DATABASE`命令。这确保了命令不会被回滚,并且允许在函数内部间接调用删除数据库的操作。
摘要由CSDN通过智能技术生成

I have a function that looks like this:

BEGIN

DROP DATABASE IF EXISTS db_1;

END;

I'm getting the following error:

ERROR: DROP DATABASE cannot be executed from a function or multi-command string.

Is it not possible to drop a database from a stored procedure in PostgreSQL? I'm using plpgsql.

解决方案

The error message is just a s clear as the manual on this:

DROP DATABASE cannot be executed inside a transaction block.

A plgpsql function is surrounded by a transaction block automatically. The long and the short of it: you cannot do that - directly. Is there a particular reason you can't just call the DDL command?

DROP database $mydb;

You can circumvent these restrictions with the additional module dblink as @Igor suggested. You need to install it once per database - the one where you call dblink functions, not the (other) one you execute commands in.

Allows you to write a function using dblink_exec() like this:

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() prevents possible SQL injection.

Call:

SELECT f_drop_db('mydb');

On success you see:

DROP DATABASE

The connection string could even point to the same db your session runs in. The command runs outside a transaction block, which has two consequences:

It cannot be rolled back.

It allows you to call DROP DATABASE "by way of a proxy" from within a function.

You could create a FOREIGN DATA WRAPPER and a FOREIGN SERVER to store a connection and simplify the call:

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');

Using default maintenance db postgres, which would be obvious choice. But any db is possible.

Simplified function making use of that:

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$;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
PostgreSQL支持存储过程存储过程是一组SQL语句的集合,可以接受参数并返回结果。在PostgreSQL存储过程可以用PL/pgSQL来编写。 下面是一个简单的存储过程的例子: ```sql CREATE OR REPLACE FUNCTION get_customer_info(customer_id integer) RETURNS TABLE (name text, email text, phone text) AS $$ BEGIN RETURN QUERY SELECT name, email, phone FROM customers WHERE id = customer_id; END; $$ LANGUAGE plpgsql; ``` 上面的存储过程接受一个customer_id参数,并返回一个包含name、email和phone的结果集。现在,我们可以调用这个存储过程: ```sql SELECT * FROM get_customer_info(1); ``` 这将返回id为1的客户的信息。 下面是一个更复杂的存储过程的例子,它将在orders表创建一个新订单,并更新相关的库存: ```sql CREATE OR REPLACE FUNCTION create_order(customer_id integer, product_id integer, quantity integer) RETURNS integer AS $$ DECLARE order_id integer; product_stock integer; BEGIN SELECT stock INTO product_stock FROM products WHERE id = product_id FOR UPDATE; IF product_stock < quantity THEN RAISE EXCEPTION 'Insufficient stock'; END IF; BEGIN INSERT INTO orders (customer_id, product_id, quantity) VALUES (customer_id, product_id, quantity) RETURNING id INTO order_id; UPDATE products SET stock = stock - quantity WHERE id = product_id; EXCEPTION WHEN unique_violation THEN RAISE EXCEPTION 'Duplicate order'; END; RETURN order_id; END; $$ LANGUAGE plpgsql; ``` 上面的存储过程接受三个参数:customer_id、product_id和quantity,并返回新订单的id。如果库存不足,它将抛出一个异常。如果订单已经存在,则也会抛出一个异常。 现在,我们可以调用这个存储过程: ```sql SELECT create_order(1, 2, 10); ``` 这将创建一个由客户1购买10个id为2的产品的新订单,并返回订单的id。 在PostgreSQL存储过程是非常强大的工具,可以用于执行复杂的数据库操作。如果您想了解更多关于PL/pgSQL的信息,请参考官方文档。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值