【问题标题】:How can I drop all the tables in a PostgreSQL database?如何删除 PostgreSQL 数据库中的所有表?
【发布时间】:2011-03-20 15:08:19
【问题描述】:

如何从命令行删除 PostgreSQL 中的所有表?

我不想删除数据库本身,只删除所有表和其中的所有数据。

【问题讨论】:

  • 你在说什么命令行?据我们所知,您正在寻找 Windows PowerShell 实施。
  • 对不起。在 Unix 上工作,在命令行输入 'psql' 之后 - 所以 psql 命令行环境本身。
  • DROP SCHEMA 公共级联; -- 颤抖
  • @0fnt 你必须做'CREATE SCHEMA public;'再次添加新表(发现困难)
  • 顺便说一句,当您删除 public 时,您会丢失所有已安装的扩展。

标签: postgresql


【解决方案1】:

如果您的所有表都在一个架构中,则此方法可能有效(以下代码假定您的架构名称为 public)

DROP SCHEMA public CASCADE;
CREATE SCHEMA public;

如果您使用的是 PostgreSQL 9.3 或更高版本,您可能还需要恢复默认授权。

GRANT ALL ON SCHEMA public TO postgres;
GRANT ALL ON SCHEMA public TO public;

【讨论】:

  • 请注意,这也会删除公共架构中定义的所有函数、视图等。
  • 请注意,这不会删除系统表(例如以 pg_ 开头的那些),因为它们位于不同的架构中,pg_catalog。
  • 这将创建模式 w/ OWNER 设置为您登录到 psql 的用户。这将与以不同用户身份登录的应用程序发生冲突。在这种情况下,您还需要运行“ALTER SCHEMA public OWNER to postgres;” (或您的应用用来创建表格的任何用户)
  • 从另一个答案中提出这一点,您可能希望在创建后有一个GRANT ALL ON SCHEMA public TO public;。
  • @Federico 为什么要在创建后使用GRANT ALL?
【解决方案2】:

您可以编写一个查询来生成这样的 SQL 脚本:

select 'drop table "' || tablename || '" cascade;' from pg_tables;

或者:

select 'drop table if exists "' || tablename || '" cascade;' from pg_tables;

如果某些表由于前一句中的级联选项而自动删除。

此外,如 cmets 中所述,您可能希望按模式名称过滤要删除的表:

select 'drop table if exists "' || tablename || '" cascade;' 
  from pg_tables
 where schemaname = 'public'; -- or any other schema

然后运行它。

Glorious COPY+PASTE 也可以。

【讨论】:

  • 我想你的意思是:你可以写一个这样的查询... ...然后运行查询的输出
  • select '如果存在则删除表 "' || 表名 || '" 级联;'来自 pg_tables;将确保大写的表格也被正确删除。
  • LenW 在他的回答中添加的子句“where schemaname = 'public'”对于将删除范围缩小到仅您管理的数据库而不是系统的数据库非常有用
  • @jwg:还有,因为有时你没有drop schema public cascade;的权限,但你几乎总是有删除表的权限。
  • 非公共模式的版本:select 'drop table if exists "' || schemaname || '"."' || tablename || '" cascade;'来自 pg_tables 其中 schemaname = 'user_data';
【解决方案3】:

截至撰写本文时(2014 年 1 月),最被接受的答案是:

drop schema public cascade;
create schema public;

这确实有效,但是如果您打算将公共架构恢复到其原始状态,这并不能完全完成任务。在 pgAdmin III for PostgreSQL 9.3.1 下,如果您单击以这种方式创建的“公共”模式并查看“SQL 窗格”,您将看到以下内容:

-- Schema: public

-- DROP SCHEMA public;

CREATE SCHEMA public
  AUTHORIZATION postgres;

但是,相比之下,全新的数据库将具有以下内容:

-- Schema: public

-- DROP SCHEMA public;

CREATE SCHEMA public
  AUTHORIZATION postgres;

GRANT ALL ON SCHEMA public TO postgres;
GRANT ALL ON SCHEMA public TO public;
COMMENT ON SCHEMA public
  IS 'standard public schema';

对于我使用创建数据库表 (web2py) 的 python web 框架,使用前者会导致问题:

<class 'psycopg2.ProgrammingError'> no schema has been selected to create in 

所以在我看来,完全正确的答案是:

DROP SCHEMA public CASCADE;
CREATE SCHEMA public;
GRANT ALL ON SCHEMA public TO postgres;
GRANT ALL ON SCHEMA public TO public;
COMMENT ON SCHEMA public IS 'standard public schema';

还要注意在 pgAdmin III 中发出这些命令,我​​使用了查询工具(放大镜图标“执行 abritrary SQL 查询”)或者您可以使用插件-> PSQL 控制台

注意

如果您安装了任何扩展,它们将在您删除架构时被删除,因此您应该记下您需要安装的内容,然后根据需要执行语句。例如

CREATE EXTENSION postgis;

【讨论】:

  • 已确认。两行解决方案(drop 然后create)曾经在 PostgreSQL 9.1 上工作。升级到9.3后,需要多出两个grant。
  • 再确认一下:使用Django,我得到了同样的错误;我需要在 django 与数据库交互之前运行这些授权。
  • 这很好用,除了我还需要重新安装一些扩展:如果不存在 hstore,则创建扩展;如果不存在 pgcrypto,则创建扩展;
  • 为了简洁起见,两个GRANT都可以一行完成:GRANT ALL ON SCHEMA public TO postgres, public;
【解决方案4】:

您可以删除所有表格

DO $$ DECLARE
    r RECORD;
BEGIN
    -- if the schema you operate on is not "current", you will want to
    -- replace current_schema() in query with 'schematodeletetablesfrom'
    -- *and* update the generate 'DROP...' accordingly.
    FOR r IN (SELECT tablename FROM pg_tables WHERE schemaname = current_schema()) LOOP
        EXECUTE 'DROP TABLE IF EXISTS ' || quote_ident(r.tablename) || ' CASCADE';
    END LOOP;
END $$;

IMO 这比 drop schema public 好,因为您不需要重新创建 schema 并恢复所有授权。

额外的好处是这不需要外部脚本语言,也不需要将生成的 SQL 复制粘贴回解释器。

【讨论】:

  • 感谢您发布此信息!我不能使用drop schema 技巧,因为用户不是架构的所有者,只是表的所有者。这个虽然有效:)
  • 非常干净和具体...很好的解决方案,也应该被接受 - 您甚至可以添加到 where 子句以限制要保留的表,如 PostGIS 等扩展程序所需的那样...
  • 我建议将EXECUTE 'DROP TABLE IF EXISTS ' || quote_ident(r.tablename) || ' CASCADE'; 更改为:EXECUTE format('DROP TABLE IF EXISTS %I CASCADE', quote_ident(r.tablename));
  • 我很高兴几年前我支持了这个 - 这是我支持的唯一一个问题,所以我会知道我使用了哪一个。我对自己印象深刻,也为自己感到羞耻。
  • 这应该是公认的答案!
【解决方案5】:

如果您要删除的所有内容由同一用户拥有,那么您可以使用:

drop owned by the_user;

这将丢弃用户拥有的一切。

这包括the_user 拥有(=created )。

您必须将the_user 替换为实际用户名,目前没有选项可以删除“当前用户”的所有内容。即将推出的 9.5 版本将有选项drop owned by current_user。

手册中的更多详细信息:http://www.postgresql.org/docs/current/static/sql-drop-owned.html

【讨论】:

  • 这删除了用户拥有的所有模式(我不想这样做)。
  • @PeterL:这在手册中有明确记录,但我编辑了我的帖子以明确“一切”真正意味着一切
  • 我会使用 current_user 拥有的 drop;这样您甚至不必担心输入正确的用户名。
  • 其实对我来说是一个非常好的解决方案。我的数据库和 public 架构归 postgres 所有,但其他所有内容都归特定用户所有,因此删除该用户拥有的所有内容都会清除数据库除了的架构。
  • 如果您在数据库中为特定应用程序(一组东西)创建了特定用户并希望完全删除该用户,则最佳答案:+1:
【解决方案6】:

根据上面的 Pablo,就大小写而言,只是从特定模式中删除:

select 'drop table "' || tablename || '" cascade;' 
from pg_tables where schemaname = 'public';

【讨论】:

  • 我用过这个,它对我有用。我认为where schemaname='public' 部分很重要?
  • @ibic 如果您忽略了这一点,您可能还会尝试删除所有内部 postgres 表,这很可能不是您想要的。
  • 更安全的选择是:select 'drop table "' || tablename || '" cascade;' from pg_tables where tableowner = 'some_user';
【解决方案7】:

这是一个非常有趣的问题,您可以通过多种方式完成它:

1。通过删除并重新创建当前架构

这里,一般情况下,我们默认有一个public 架构。所以,我以它为例。

-- Recreate the schema
DROP SCHEMA public CASCADE;
CREATE SCHEMA public;

-- Restore default permissions
GRANT ALL ON SCHEMA public TO postgres;
GRANT ALL ON SCHEMA public TO public;

如果您使用的是 PostgreSQL 9.3 或更高版本,您可能还需要恢复默认授权。

优点:

这将清除整个架构并将其重新创建为新架构。

缺点:

您也会失去其他实体,例如 Functions、Views、Materialized views 等。

2。通过使用从pg_tables 表中获取所有表名。

PostgreSQL 将所有表存储在其名为pg_table 的记录表中​​。

SELECT
  'DROP TABLE IF EXISTS "' || tablename || '" CASCADE;' 
from
  pg_tables WHERE schemaname = 'public';

如您所见,通过使用子查询,我们可以从架构中删除整个表。

优点:

当其他数据实体很重要并且您只想从架构中删除表时,这种方法对您很有帮助。

3。终端

  • 在您的 shell 上使用 postgres 用户登录
$ sudo -u postgres psql
  • 连接您的数据库
$ \c mydatabase

粘贴这些命令:

DROP SCHEMA public CASCADE;
CREATE SCHEMA public;
     
GRANT ALL ON SCHEMA public TO postgres;
GRANT ALL ON SCHEMA public TO public;

注意:这一堆命令与第一点类似,所以利弊保持不变。

【讨论】:

  • #2 对我来说效果很好。我不得不删除所有的 " 但是,没关系
【解决方案8】:
drop schema public cascade;

应该可以解决问题。

【讨论】:

  • 请注意,这也会删除公共架构中定义的所有函数、视图等。
  • 您还必须在之后再次重新创建才能使用CREATE SCHEMA public; 重新添加表格。另请参阅stackoverflow.com/a/14286370 了解更多信息
【解决方案9】:

以下步骤可能会有所帮助(对于 linux 用户):

  1. 首先通过以下命令进入postgres命令提示符:

    sudo -u postgres psql
    
  2. 通过这个命令进入数据库(我的数据库名称是:maoss):

    \c maoss
    
  3. 现在输入删除所有表的命令:

    DROP SCHEMA public CASCADE;
    CREATE SCHEMA public;
    
    GRANT ALL ON SCHEMA public TO postgres;
    GRANT ALL ON SCHEMA public TO public;
    
  4. 现在通过以下命令退出psql:

    \q
    

【讨论】:

  • 按照我的 ubuntu 19.04 上的步骤进行操作,完美无缺!
  • @AlexM.M.很高兴听到这个消息:)
【解决方案10】:

继 Pablo 和 LenW 之后,这里有一个单行代码,可以同时完成所有准备和执行:

psql -U $PGUSER $PGDB -t -c "select 'drop table \"' || tablename || '\" cascade;' from pg_tables where schemaname = 'public'" | psql -U $PGUSER $PGDB

注意:使用您想要的值设置或替换 $PGUSER 和 $PGDB

【讨论】:

    【解决方案11】:

    如果您有 PL/PGSQL 过程语言 installed,您可以使用以下命令删除所有内容,而无需使用 shell/Perl 外部脚本。

    DROP FUNCTION IF EXISTS remove_all();
    
    CREATE FUNCTION remove_all() RETURNS void AS $$
    DECLARE
        rec RECORD;
        cmd text;
    BEGIN
        cmd := '';
    
        FOR rec IN SELECT
                'DROP SEQUENCE ' || quote_ident(n.nspname) || '.'
                    || quote_ident(c.relname) || ' CASCADE;' AS name
            FROM
                pg_catalog.pg_class AS c
            LEFT JOIN
                pg_catalog.pg_namespace AS n
            ON
                n.oid = c.relnamespace
            WHERE
                relkind = 'S' AND
                n.nspname NOT IN ('pg_catalog', 'pg_toast') AND
                pg_catalog.pg_table_is_visible(c.oid)
        LOOP
            cmd := cmd || rec.name;
        END LOOP;
    
        FOR rec IN SELECT
                'DROP TABLE ' || quote_ident(n.nspname) || '.'
                    || quote_ident(c.relname) || ' CASCADE;' AS name
            FROM
                pg_catalog.pg_class AS c
            LEFT JOIN
                pg_catalog.pg_namespace AS n
            ON
                n.oid = c.relnamespace WHERE relkind = 'r' AND
                n.nspname NOT IN ('pg_catalog', 'pg_toast') AND
                pg_catalog.pg_table_is_visible(c.oid)
        LOOP
            cmd := cmd || rec.name;
        END LOOP;
    
        FOR rec IN SELECT
                'DROP FUNCTION ' || quote_ident(ns.nspname) || '.'
                    || quote_ident(proname) || '(' || oidvectortypes(proargtypes)
                    || ');' AS name
            FROM
                pg_proc
            INNER JOIN
                pg_namespace ns
            ON
                (pg_proc.pronamespace = ns.oid)
            WHERE
                ns.nspname =
                'public'
            ORDER BY
                proname
        LOOP
            cmd := cmd || rec.name;
        END LOOP;
    
        EXECUTE cmd;
        RETURN;
    END;
    $$ LANGUAGE plpgsql;
    
    SELECT remove_all();
    

    建议您将其复制到文件中,然后使用“--file”或“-f”选项将文件作为输入传递给 psql,而不是在“psql”提示符下输入:

    psql -f clean_all_pg.sql
    

    应归功于信用:我编写了该函数,但认为查询(或至少第一个查询)来自多年前 pgsql 邮件列表中的某个人。不记得确切的时间或哪个。

    【讨论】:

      【解决方案12】:

      如果您无论如何都想对所有表进行核对,则可以通过将所有表放入单个语句中来省去诸如 CASCADE 之类的细节。这也使执行速度更快。

      SELECT 'TRUNCATE TABLE ' || string_agg('"' || tablename || '"', ', ') || ';' 
      FROM pg_tables WHERE schemaname = 'public';
      

      直接执行:

      DO $$
      DECLARE tablenames text;
      BEGIN    
          tablenames := string_agg('"' || tablename || '"', ', ') 
              FROM pg_tables WHERE schemaname = 'public';
          EXECUTE 'TRUNCATE TABLE ' || tablenames;
      END; $$
      

      将TRUNCATE 替换为DROP(如果适用)。

      【讨论】:

      • 当不在public架构上操作时,不要忘记在表达式中包含架构名称:string_agg(quote_ident(schemaname) || '.' || quote_ident(tablename), ', '),而不是仅仅传递表名。
      【解决方案13】:

      为了方便将生成的 SQL 命令作为单个字符串返回,我稍微修改了 Pablo 的答案:

      select string_agg('drop table "' || tablename || '" cascade', '; ') 
      from pg_tables where schemaname = 'public'
      

      【讨论】:

        【解决方案14】:

        以防万一...清理 Postgresql 数据库的简单 Python 脚本

        import psycopg2
        import sys
        
        # Drop all tables from a given database
        
        try:
            conn = psycopg2.connect("dbname='akcja_miasto' user='postgres' password='postgres'")
            conn.set_isolation_level(0)
        except:
            print "Unable to connect to the database."
        
        cur = conn.cursor()
        
        try:
            cur.execute("SELECT table_schema,table_name FROM information_schema.tables WHERE table_schema = 'public' ORDER BY table_schema,table_name")
            rows = cur.fetchall()
            for row in rows:
                print "dropping table: ", row[1]   
                cur.execute("drop table " + row[1] + " cascade") 
            cur.close()
            conn.close()        
        except:
            print "Error: ", sys.exc_info()[1]
        

        确保在复制后缩进是正确的,因为 Python 依赖它。

        【讨论】:

        • 作品具有魅力。我选择这个是因为我喜欢硬编码数据库连接信息——我想做的最后一件事就是打错数据库!而且,我的表格列表也是一个移动的目标。
        • conn.set_isolation_level(0) 非常重要,否则 drop 查询就会卡住
        【解决方案15】:

        在 pgAdmin 中使用这个脚本:

        DO $$
        DECLARE 
            brow record;
        BEGIN
            FOR brow IN (select 'drop table "' || tablename || '" cascade;' as table_name from pg_tables where schemaname = 'public') LOOP
                EXECUTE brow.table_name;
            END LOOP;
        END; $$
        

        【讨论】:

        • 那个 sql 对我来说失败了。我使用 SELECT concat('drop table ',tablename, ' cascade ;') AS drop_table_sql FROM pg_tables WHERE schemaname = 'public'
        • 一定是我做错了什么,卢卡。我刚刚又试了一次,它成功了。
        【解决方案16】:

        如果你想删除数据(不是删除表):

        -- Truncate tables and restart sequnces
        SELECT 'TRUNCATE TABLE "' || table_schema || '"."' || table_name || '" RESTART IDENTITY CASCADE;' 
        FROM information_schema.tables 
        WHERE table_catalog = '<database>' AND table_schema = '<schema>';
        

        或者如果你想删除表,你可以使用这个 sql:

        -- For tables
        SELECT 'DROP TABLE "' || table_schema || '"."' || table_name || '" CASCADE;' 
        FROM information_schema.tables 
        WHERE table_catalog = '<database>' AND table_schema = '<schema>';
        
        -- For sequences
        SELECT 'DROP SEQUENCE d_a_seq "' || sequence_schema || '"."' || sequence_name || '";' 
        FROM information_schema.sequences 
        WHERE sequence_catalog = '<database>' AND sequence_schema = '<schema>';
        

        【讨论】:

          【解决方案17】:

          您可以使用 string_agg 函数创建一个逗号分隔的列表,非常适合 DROP TABLE。 来自 bash 脚本:

          #!/bin/bash
          TABLES=`psql $PGDB -t --command "SELECT string_agg(table_name, ',') FROM information_schema.tables WHERE table_schema='public'"`
          
          echo Dropping tables:${TABLES}
          psql $PGDB --command "DROP TABLE IF EXISTS ${TABLES} CASCADE"
          

          【讨论】:

          • 应该是#!/bin/sh
          【解决方案18】:

          注意:我的回答是关于真正删除表和其他数据库对象;对于deleting all data in the tables, i.e. truncating all tables,Endre Both 在一个月后提供了同样执行良好(直接执行)的语句。

          对于不能只使用DROP SCHEMA public CASCADE;、DROP OWNED BY current_user; 或其他东西的情况,这是我编写的独立 SQL 脚本,它是事务安全的(即,您可以将其放在 BEGIN; 和 @ 987654328@ 只是测试它或COMMIT; 实际执行)并清理“所有”数据库对象......好吧,我们的应用程序使用的数据库中使用的所有对象,或者我可以明智地添加,即:

          • 表上的触发器
          • 表格约束(FK、PK、CHECK、UNIQUE)
          • 指标
          • VIEWs(正常或具体化)
          • 表格
          • 序列
          • 例程(聚合函数、函数、过程)
          • 所有非默认(即不是public 或DB-internal)模式“我们”拥有:该脚本在以“非数据库超级用户”身份运行时很有用;超级用户可以删除 所有 模式(不过,真正重要的模式仍然被明确排除)
          • 扩展(用户提供,但我通常故意将它们留在里面)

          没有删除是(有些是故意的;有些只是因为我在我们的数据库中没有示例):

          • public 架构(例如,用于其中的扩展提供的东西)
          • 排序规则和其他语言环境的东西
          • 事件触发器
          • 文本搜索内容,……(请参阅 here 了解我可能错过的其他内容)
          • 角色或其他安全设置
          • 复合类型
          • 烤面包桌
          • FDW 和外部表

          当您要恢复的转储与数据库具有不同的数据库架构版本(例如,使用 Debian dbconfig-common、Flyway 或 Liquibase/DB-Manul)时,这真的非常有用你想把它恢复到。

          我还有一个版本可以删除“除了两个表和属于它们的所有内容”(一个序列,手动测试,抱歉,我知道,无聊)以防有人感兴趣;差异很小。有兴趣请联系我或check this repo。

          SQL

          -- Copyright © 2019, 2020
          --      mirabilos <t.glaser@tarent.de>
          --
          -- Provided that these terms and disclaimer and all copyright notices
          -- are retained or reproduced in an accompanying document, permission
          -- is granted to deal in this work without restriction, including un‐
          -- limited rights to use, publicly perform, distribute, sell, modify,
          -- merge, give away, or sublicence.
          --
          -- This work is provided “AS IS” and WITHOUT WARRANTY of any kind, to
          -- the utmost extent permitted by applicable law, neither express nor
          -- implied; without malicious intent or gross negligence. In no event
          -- may a licensor, author or contributor be held liable for indirect,
          -- direct, other damage, loss, or other issues arising in any way out
          -- of dealing in the work, even if advised of the possibility of such
          -- damage or existence of a defect, except proven that it results out
          -- of said person’s immediate fault when using the work as intended.
          -- -
          -- Drop everything from the PostgreSQL database.
          
          DO $$
          DECLARE
                  q TEXT;
                  r RECORD;
          BEGIN
                  -- triggers
                  FOR r IN (SELECT pns.nspname, pc.relname, pt.tgname
                          FROM pg_catalog.pg_trigger pt, pg_catalog.pg_class pc, pg_catalog.pg_namespace pns
                          WHERE pns.oid=pc.relnamespace AND pc.oid=pt.tgrelid
                              AND pns.nspname NOT IN ('information_schema', 'pg_catalog', 'pg_toast')
                              AND pt.tgisinternal=false
                      ) LOOP
                          EXECUTE format('DROP TRIGGER %I ON %I.%I;',
                              r.tgname, r.nspname, r.relname);
                  END LOOP;
                  -- constraints #1: foreign key
                  FOR r IN (SELECT pns.nspname, pc.relname, pcon.conname
                          FROM pg_catalog.pg_constraint pcon, pg_catalog.pg_class pc, pg_catalog.pg_namespace pns
                          WHERE pns.oid=pc.relnamespace AND pc.oid=pcon.conrelid
                              AND pns.nspname NOT IN ('information_schema', 'pg_catalog', 'pg_toast')
                              AND pcon.contype='f'
                      ) LOOP
                          EXECUTE format('ALTER TABLE ONLY %I.%I DROP CONSTRAINT %I;',
                              r.nspname, r.relname, r.conname);
                  END LOOP;
                  -- constraints #2: the rest
                  FOR r IN (SELECT pns.nspname, pc.relname, pcon.conname
                          FROM pg_catalog.pg_constraint pcon, pg_catalog.pg_class pc, pg_catalog.pg_namespace pns
                          WHERE pns.oid=pc.relnamespace AND pc.oid=pcon.conrelid
                              AND pns.nspname NOT IN ('information_schema', 'pg_catalog', 'pg_toast')
                              AND pcon.contype<>'f'
                      ) LOOP
                          EXECUTE format('ALTER TABLE ONLY %I.%I DROP CONSTRAINT %I;',
                              r.nspname, r.relname, r.conname);
                  END LOOP;
                  -- indicēs
                  FOR r IN (SELECT pns.nspname, pc.relname
                          FROM pg_catalog.pg_class pc, pg_catalog.pg_namespace pns
                          WHERE pns.oid=pc.relnamespace
                              AND pns.nspname NOT IN ('information_schema', 'pg_catalog', 'pg_toast')
                              AND pc.relkind='i'
                      ) LOOP
                          EXECUTE format('DROP INDEX %I.%I;',
                              r.nspname, r.relname);
                  END LOOP;
                  -- normal and materialised views
                  FOR r IN (SELECT pns.nspname, pc.relname
                          FROM pg_catalog.pg_class pc, pg_catalog.pg_namespace pns
                          WHERE pns.oid=pc.relnamespace
                              AND pns.nspname NOT IN ('information_schema', 'pg_catalog', 'pg_toast')
                              AND pc.relkind IN ('v', 'm')
                      ) LOOP
                          EXECUTE format('DROP VIEW %I.%I;',
                              r.nspname, r.relname);
                  END LOOP;
                  -- tables
                  FOR r IN (SELECT pns.nspname, pc.relname
                          FROM pg_catalog.pg_class pc, pg_catalog.pg_namespace pns
                          WHERE pns.oid=pc.relnamespace
                              AND pns.nspname NOT IN ('information_schema', 'pg_catalog', 'pg_toast')
                              AND pc.relkind='r'
                      ) LOOP
                          EXECUTE format('DROP TABLE %I.%I;',
                              r.nspname, r.relname);
                  END LOOP;
                  -- sequences
                  FOR r IN (SELECT pns.nspname, pc.relname
                          FROM pg_catalog.pg_class pc, pg_catalog.pg_namespace pns
                          WHERE pns.oid=pc.relnamespace
                              AND pns.nspname NOT IN ('information_schema', 'pg_catalog', 'pg_toast')
                              AND pc.relkind='S'
                      ) LOOP
                          EXECUTE format('DROP SEQUENCE %I.%I;',
                              r.nspname, r.relname);
                  END LOOP;
                  -- extensions (only if necessary; keep them normally)
                  FOR r IN (SELECT pns.nspname, pe.extname
                          FROM pg_catalog.pg_extension pe, pg_catalog.pg_namespace pns
                          WHERE pns.oid=pe.extnamespace
                              AND pns.nspname NOT IN ('information_schema', 'pg_catalog', 'pg_toast')
                      ) LOOP
                          EXECUTE format('DROP EXTENSION %I;', r.extname);
                  END LOOP;
                  -- aggregate functions first (because they depend on other functions)
                  FOR r IN (SELECT pns.nspname, pp.proname, pp.oid
                          FROM pg_catalog.pg_proc pp, pg_catalog.pg_namespace pns, pg_catalog.pg_aggregate pagg
                          WHERE pns.oid=pp.pronamespace
                              AND pns.nspname NOT IN ('information_schema', 'pg_catalog', 'pg_toast')
                              AND pagg.aggfnoid=pp.oid
                      ) LOOP
                          EXECUTE format('DROP AGGREGATE %I.%I(%s);',
                              r.nspname, r.proname,
                              pg_get_function_identity_arguments(r.oid));
                  END LOOP;
                  -- routines (functions, aggregate functions, procedures, window functions)
                  IF EXISTS (SELECT * FROM pg_catalog.pg_attribute
                          WHERE attrelid='pg_catalog.pg_proc'::regclass
                              AND attname='prokind' -- PostgreSQL 11+
                      ) THEN
                          q := 'CASE pp.prokind
                                  WHEN ''p'' THEN ''PROCEDURE''
                                  WHEN ''a'' THEN ''AGGREGATE''
                                  ELSE ''FUNCTION''
                              END';
                  ELSIF EXISTS (SELECT * FROM pg_catalog.pg_attribute
                          WHERE attrelid='pg_catalog.pg_proc'::regclass
                              AND attname='proisagg' -- PostgreSQL ≤10
                      ) THEN
                          q := 'CASE pp.proisagg
                                  WHEN true THEN ''AGGREGATE''
                                  ELSE ''FUNCTION''
                              END';
                  ELSE
                          q := '''FUNCTION''';
                  END IF;
                  FOR r IN EXECUTE 'SELECT pns.nspname, pp.proname, pp.oid, ' || q || ' AS pt
                          FROM pg_catalog.pg_proc pp, pg_catalog.pg_namespace pns
                          WHERE pns.oid=pp.pronamespace
                              AND pns.nspname NOT IN (''information_schema'', ''pg_catalog'', ''pg_toast'')
                      ' LOOP
                          EXECUTE format('DROP %s %I.%I(%s);', r.pt,
                              r.nspname, r.proname,
                              pg_get_function_identity_arguments(r.oid));
                  END LOOP;
                  -- nōn-default schemata we own; assume to be run by a not-superuser
                  FOR r IN (SELECT pns.nspname
                          FROM pg_catalog.pg_namespace pns, pg_catalog.pg_roles pr
                          WHERE pr.oid=pns.nspowner
                              AND pns.nspname NOT IN ('information_schema', 'pg_catalog', 'pg_toast', 'public')
                              AND pr.rolname=current_user
                      ) LOOP
                          EXECUTE format('DROP SCHEMA %I;', r.nspname);
                  END LOOP;
                  -- voilà
                  RAISE NOTICE 'Database cleared!';
          END; $$;
          

          在 PostgreSQL 9.6 (jessie-backports) 上经过测试,除了后来添加的内容(Clément Prévost 贡献的extensions)。在 9.6 和 12.2 上测试了骨料去除,也在 12.2 上测试了过程去除。欢迎进行错误修复和进一步改进!

          【讨论】:

          • 上述脚本存在错误,因为它没有区分函数和过程:DROP FUNCTION 过程失败,反之亦然。我将函数部分修改为:AND pp.prokind ='f' -- Function 或 AND pp.prokind ='p' -- Procedure
          • @BogeyMan 这不是错误,记录了聚合函数的遗漏,并且记录了脚本仅在 9.6 上进行测试。但我将您的评论铭记于心,并对其进行了调整,以处理 ≤ 10.x 上的聚合 (proisagg) 和 ≥ 11 上的聚合和过程 (prokind)(动态检查),并测试了这两个 ☻ 感谢您的提示。跨度>
          【解决方案19】:

          您需要删除表格和序列,这对我有用

          psql -qAtX -c "select 'DROP TABLE IF EXISTS ' || quote_ident(table_schema) || '.' || quote_ident(table_name) || ' CASCADE;' FROM information_schema.tables where table_type = 'BASE TABLE' and not table_schema ~ '^(information_schema|pg_.*)$'" | psql -qAtX
          psql -qAtX -c "select 'DROP SEQUENCE IF EXISTS ' || quote_ident(relname) || ' CASCADE;' from pg_statio_user_sequences;" | psql -qAtX
          

          在运行命令之前,您可能需要 sudo/su 到 postgres 用户或(导出连接详细信息 PGHOST、PGPORT、PGUSER 和 PGPASSWORD)然后 export PGDATABASE=yourdatabase

          【讨论】:

            【解决方案20】:

            Rails 的 Rake 任务,用于销毁当前数据库中的所有表

            namespace :db do
              # rake db:drop_all_tables
              task drop_all_tables: :environment do
                query = <<-QUERY
                  SELECT
                    table_name
                  FROM
                    information_schema.tables
                  WHERE
                    table_type = 'BASE TABLE'
                  AND
                    table_schema NOT IN ('pg_catalog', 'information_schema');
                QUERY
            
                connection = ActiveRecord::Base.connection
                results    = connection.execute query
            
                tables = results.map do |line|
                  table_name = line['table_name']
                end.join ", "
            
                connection.execute "DROP TABLE IF EXISTS #{ tables } CASCADE;"
              end
            end
            

            【讨论】:

            • 说 AND table_schema = 'public' 而不是 NOT IN 该列表可能更简单/更安全。
            • 出于某种原因,我的架构是使用填充数据创建的。这个耙子有效。所以在rake db:create 之后,我运行它。您可以按照史蒂夫提示删除代码 table_name = 并将 ", " 更改为 "," 和 #{ tables } fo #{tables}
            【解决方案21】:

            我通过处理视图增强了 jamie 的 bash 方法,因为他只尊重默认的表类型“基表”。

            以下 bash 代码先删除视图,然后再删除所有其余部分

            #!/usr/bin/env bash
            
            PGDB="yourDB"
            # By exporting user & pass your dont need to interactively type them on execution
            export PGUSER="PGusername"
            export PGPASSWORD="PGpassword"
            
            VIEWS=`psql -d $PGDB -t --command "SELECT string_agg(table_name, ',') FROM information_schema.tables WHERE table_schema='public' AND table_type='VIEW'"`
            BASETBLS=`psql -d $PGDB -t --command "SELECT string_agg(table_name, ',') FROM information_schema.tables WHERE table_schema='public' AND table_type='BASE TABLE'"`
            
            echo Dropping views:${VIEWS}
            psql $PGDB --command "DROP VIEW IF EXISTS ${VIEWS} CASCADE"
            echo Dropping tables:${BASETBLS}
            psql $PGDB --command "DROP TABLE IF EXISTS ${BASETBLS} CASCADE"
            

            【讨论】:

            • 很棒的脚本......刚刚使用它并且像魅力一样工作。我还为序列添加了一行:SEQUENCES=psql -d $PGDB -t --command "SELECT string_agg(sequence_name, ',') FROM information_schema.sequences WHERE sequence_schema='public' AND sequence_catalog='$PGDB'"
            【解决方案22】:

            在 Windows 批处理文件中:

            @echo off
            FOR /f "tokens=2 delims=|" %%G IN ('psql --host localhost --username postgres --command="\dt" YOUR_TABLE_NAME') DO (
               psql --host localhost --username postgres --command="DROP table if exists %%G cascade" sfkb
               echo table %%G dropped
            )
            

            【讨论】:

              【解决方案23】:

              将 PSQL 与 \gexec 一起使用

              这是一个比迄今为止更全面的查询,因为它适用于特殊的表名。

              SELECT FORMAT('DROP TABLE %I.%I.%I CASCADE;', table_catalog, table_schema, table_name)
              FROM information_schema.tables
              WHERE table_type = 'BASE TABLE'
                AND table_schema <> 'information_schema'
                AND table_schema NOT LIKE 'pg_%';
              

              您可以预览要运行的命令,在psql中运行后输入\gexec即可执行此查询的输出。

              注意:CASCADE 的使用将删除所有依赖表的东西(如 VIEWs)

              【讨论】:

              • 史诗,太棒了。我不知道你能做到这一点。为我节省了大量时间,谢谢!
              【解决方案24】:

              好吧,因为我喜欢从命令行工作...

              psql -U &lt;user&gt; -d &lt;mydb&gt; -c '\dt' | cut -d ' ' -f 4 | sed -e "s/^/drop table if exists /" | sed -e "s/$/;/"

              -c '\dt' 将调用列表命令。

              List of relations Schema | Name | Type | Owner --------+-------------------+-------+---------- public | _d_psidxddlparm | table | djuser public | _d_psindexdefn | table | djuser

              cut -d ' ' -f 4 现在,通过管道将其输出抓取到第 4 个字段(使用空格作为分隔符时),即表格。

              sed 然后用于前缀 drop table 和后缀 ; 命令分隔符。

              | egrep '_d_' - 将其通过管道传输到grep 中,这样您就可以更有选择性地选择要删除的表。

              drop table if exists _d_psidxddlparm; drop table if exists _d_psindexdefn;

              注意:如所写,这将为\dt 命令输出的列标题和最后的总行数生成虚假行。我通过 grepping 来避免这种情况,但你可以使用 head 和 tail。

              【讨论】:

                【解决方案25】:

                最简单的方法是删除公共架构,正如其他人在之前的答案中所建议的那样。但是,这不是一个好方法。您永远不知道对已被遗忘且未记录在案的公共模式做了什么。你也不知道这是否会在未来同样有效。在 V9 中,这很好,但在 V10 中,您的所有用户都将失去对模式的访问权限,并且必须再次授予访问权限,否则您的应用程序将中断。我还没有检查 V11,但重点是,当您从一台机器移动到另一台机器、从站点到站点或从版本到版本时,您永远不知道会出现什么问题。如果您是有权访问数据库但不能访问架构的用户,也无法执行此操作。

                如果您需要以编程方式执行此操作,那么上面的其他答案涵盖了这一点,但上面的答案没有考虑的一件事是让 Postgres 为您完成工作。如果您使用带有 -c 选项的 pg_dump,如下所示:

                sudo su postgres -c "pg_dump -U postgres WhateverDB -c -f "/home/Anyone/DBBackupWhateverDB-ServerUnscheduled.sql""
                

                这将创建一个带有删除所有表的 sql 语句的数据库恢复脚本。

                如果提出问题的唯一目的是在还原之前删除表,那么您的还原将为您完成工作。

                但是,如果您需要它来做其他事情,您可以简单地从 sql 脚本中复制 drop 语句。

                【讨论】:

                  【解决方案26】:

                  只需执行下面的查询:

                  DO $$ DECLARE
                      r RECORD;
                  BEGIN
                      FOR r IN (SELECT tablename FROM pg_tables WHERE schemaname = current_schema()) LOOP
                          EXECUTE 'DROP TABLE IF EXISTS ' || quote_ident(r.tablename) || ' CASCADE';
                      END LOOP;
                  END $$;
                  

                  【讨论】:

                    【解决方案27】:

                    使用psql 的基于终端的方法最适合我。我什至创建了一个bash函数,因为它便于开发:

                    psqlDropTables() {
                        PGPASSWORD=<your password>
                        PGTABLE=<your table name>
                        PGUSER=<your pg user name>
                        PGPASSWORD=$PGPASSWORD psql -ah 127.0.0.1 $PGTABLE $PGUSER -c "
                          SELECT
                    'DROP TABLE IF EXISTS \"' || tablename || '\" CASCADE;' from
                    pg_tables WHERE schemaname = 'public';" | grep DROP | awk 'NR>1{print $0}' | sed "s/\"/'/g" | PGPASSWORD=$PGPASSWORD xargs -i  psql -ah 127.0.0.1 $PGTABLE $PGUSER -c {}
                    }
                    

                    它创建所有必需的删除表语句,如this response 中所述,将“替换为”并在数据库上运行它们。

                    【讨论】:

                      【解决方案28】:

                      这是为您准备的查询:

                      选择

                      'drop table if exists "' || tablename || '" cascade;' as pg_drop
                      

                      来自

                      pg_tables
                      

                      在哪里

                      schemaname='your schema';
                      

                      【讨论】:

                        【解决方案29】:

                        也许最简单的方法是:

                        1. 删除数据库包含以下表:

                          drop database DATABASE_NAME;

                        2. 重新创建该数据库:

                          create database DATABASE_NAME;

                        【讨论】:

                          【解决方案30】:

                          适用于 macOS。如果你有一个通过 PostgreSQL 应用程序的终端,一个简单的命令可以帮助你:

                          drop table "organisations" cascade;
                          

                          【讨论】:

                            猜你喜欢
                            • 2020-04-18
                            • 1970-01-01
                            • 2019-02-24
                            • 2016-01-13
                            • 1970-01-01
                            • 1970-01-01
                            • 2013-02-12
                            • 2011-06-11
                            • 1970-01-01
                            相关资源
                            最近更新 更多