Answers:
在PostgreSQL *中,无法在客户端连接到数据库时删除数据库。
至少没有使用该dropdb
实用程序-该实用程序只是DROP DATABASE
服务器查询的简单包装。
相当强大的解决方法如下:
使用或其他客户端,以超级用户身份连接到服务器psql
。千万不能使用你要删除的数据库。
psql -h localhost postgres postgres
现在,使用普通数据库客户端,您可以使用三个简单步骤强制删除数据库:
确保没有人可以连接到该数据库。您可以使用以下方法之一(第二种方法似乎更安全,但不会阻止来自超级用户的连接)。
/* Method 1: update system catalog */
UPDATE pg_database SET datallowconn = 'false' WHERE datname = 'mydb';
/* Method 2: use ALTER DATABASE. Superusers still can connect!
ALTER DATABASE mydb CONNECTION LIMIT 0; */
使用强制断开连接到该数据库的所有客户端的连接pg_terminate_backend
。
SELECT pg_terminate_backend(pid)
FROM pg_stat_activity
WHERE datname = 'mydb';
/* For old versions of PostgreSQL (up to 9.1), change pid to procpid:
SELECT pg_terminate_backend(procpid)
FROM pg_stat_activity
WHERE datname = 'mydb'; */
删除数据库。
DROP DATABASE mydb;
第1步要求第一种方法具有超级用户特权,而第二种方法则需要数据库所有者特权。步骤2需要超级用户权限。步骤3需要数据库所有者特权。
* 这适用于所有版本的PostgreSQL,最高版本11。
有是一种方式与外壳工具来做到这一点dropdb
和pg_ctl
(或pg_ctlcluster
在Debian和衍生物)。但是@filiprem的方法优越,原因如下:
dropdb
命令。我引用man pg_ctlcluster
:
使用该
--force
选项时,将使用“快速”模式,该模式将回滚所有活动事务,立即断开客户端的连接,从而彻底关闭客户端。如果这不起作用,请以“立即”模式再次尝试关闭,这可能会使群集处于不一致状态,从而导致下次启动时执行恢复。如果这仍然不能解决问题,则将取消邮件管理员。成功退出时以0退出,如果服务器未运行则退出,以2退出,在其他失败情况下以1退出。仅在即将关闭机器时使用此模式。
pg_ctlcluster 9.1 main restart --force
要么
pg_ctl restart -D datadir -m fast
要么
pg_ctl restart -D datadir -m immediate
紧随其后的是:
dropdb mydb
可能是在脚本中立即继承。
在我的情况下使用@filiprem的答案并简化它:
-- Connecting to the current user localhost's postgres instance
psql
-- Making sure the database exists
SELECT * from pg_database where datname = 'my_database_name'
-- Disallow new connections
UPDATE pg_database SET datallowconn = 'false' WHERE datname = 'my_database_name';
ALTER DATABASE my_database_name CONNECTION LIMIT 1;
-- Terminate existing connections
SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname = 'my_database_name';
-- Drop database
DROP DATABASE my_database_name
如果您使用的是RDS之类的方法,其中没有选择数据库的连接会将您放入默认情况下要求创建的DB中,则可以执行此变体来避免自己成为最后一个打开的连接。
DROP DATABASE IF EXISTS temporary_db_that_shouldnt_exist;
CREATE DATABASE temporary_db_that_shouldnt_exist with OWNER your_user;
\connect temporary_db_that_shouldnt_exist
SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname = 'the_db_you_want_removed';
DROP DATABASE IF EXISTS the_db_you_want_removed;
--
-- Name: the_db_you_want_removed; Type: DATABASE; Schema: -; Owner: your_user
--
CREATE DATABASE savings_champion WITH TEMPLATE = template0 ENCODING = 'UTF8' LC_COLLATE = 'en_US.UTF-8' LC_CTYPE = 'en_US.UTF-8';
ALTER DATABASE the_db_you_want_removed OWNER TO your_user;
\connect the_db_you_want_removed
DROP DATABASE IF EXISTS temporary_db_that_shouldnt_exist;