在 postgres 中删除所有共享相同前缀的表

Posted

技术标签:

【中文标题】在 postgres 中删除所有共享相同前缀的表【英文标题】:drop all tables sharing the same prefix in postgres 【发布时间】:2015-02-21 00:52:27 【问题描述】:

我想使用一个 sql 命令/查询从同一个数据库中删除所有共享相同前缀 ('supenh_agk') 的表。

【问题讨论】:

How to drop multiple tables in PostgreSQL using a wildcard的可能重复 【参考方案1】:

这是 sql server 命令,你可以试试这个,它在 postgres 中是否有效。 此查询将生成删除的 sql 脚本

SELECT 'DROP TABLE "' || TABLE_NAME || '"' 
FROM INFORMATION_SCHEMA.TABLES 
WHERE TABLE_NAME LIKE '[prefix]%'

[编辑]

begin
    for arow in
      SELECT 'DROP TABLE "' || TABLE_NAME || '"' as col1
      FROM INFORMATION_SCHEMA.TABLES 
      WHERE TABLE_NAME LIKE '[prefix]%'
    LOOP
   --RAISE NOTICE '%',    
    EXECUTE 'DROP TABLE ' || arow ;
END LOOP;
  end;

【讨论】:

好的,像这样:SELECT 'DROP TABLE' ||表名 || ';' FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME LIKE 'supenh_agk%';但是有没有办法在生成脚本后执行它??...我想使用一个命令来完成这一切,而不是复制结果代码并删除引号(“”)谢谢! @a_horse_with_no_name:- + 也在 sql server 2008 中工作以连接 + 在 postgres 中不起作用...(问题在于 postgres)。谢谢!有没有办法在 postgres 查询中使用“执行”命令? - 所以要实际执行生成的脚本(上面建议的输出)? @Roy:- 将此添加到临时表中,并循环执行每一行【参考方案2】:

要在 one 命令中执行此操作,您需要在 DO 语句(或函数)中使用带有 EXECUTE 的动态 SQL:

DO
$do$
DECLARE
   _tbl text;
BEGIN
FOR _tbl  IN
    SELECT quote_ident(table_schema) || '.'
        || quote_ident(table_name)      -- escape identifier and schema-qualify!
    FROM   information_schema.tables
    WHERE  table_name LIKE 'prefix' || '%'  -- your table name prefix
    AND    table_schema NOT LIKE 'pg\_%'    -- exclude system schemas
LOOP
   RAISE NOTICE '%',
-- EXECUTE
  'DROP TABLE ' || _tbl;  -- see below
END LOOP;
END
$do$;

这包括当前用户有权访问的所有模式中的表。为了安全起见,我排除了系统架构。

如果您没有正确转义标识符,则代码对于任何需要双引号的非标准 identifier 都会失败。 此外,您还冒着允许SQL 注入 的风险。所有用户输入都必须在动态代码中进行清理 - 其中包括用户可能提供的标识符。

有潜在危险!所有这些表都将被永久删除。我建立了一个安全。在实际执行之前检查生成的语句:注释 RAISE 并取消注释 EXECUTE

如果任何其他对象(如视图等)依赖于表,则会收到一条信息性错误消息,这会取消整个事务。如果您确信所有家属也会死亡,请附加CASCADE

  'DROP TABLE ' || _tbl || ' CASCADE;

密切相关:

Update column in multiple tables Changing all zeros (if any) across all columns (in a table) to... say 1

或者您可以在目录表pg_class 上构建,它还提供表的oid,并且速度更快:

...
FOR _tbl  IN
    SELECT c.oid::regclass::text  -- escape identifier and schema-qualify!
    FROM   pg_catalog.pg_class c
    JOIN   pg_catalog.pg_namespace n ON n.oid = c.relnamespace
    WHERE  n.nspname NOT LIKE 'pg\_%'     -- exclude system schemas
    AND    c.relname LIKE 'prefix' || '%' -- your table name prefix
    AND    c.relkind = 'r'                -- only tables
...

系统目录或信息架构?

How to check if a table exists in a given schema

c.oid::regclass 如何防御 SQL 注入?

Table name as a PostgreSQL function parameter

单个DROP 命令中完成所有操作。应该更高效一点:

DO
$do$
BEGIN
   RAISE NOTICE '%', (
-- EXECUTE (
   SELECT 'DROP TABLE ' || string_agg(format('%I.%I', schemaname, tablename), ', ')
   --  || ' CASCADE' -- optional
   FROM   pg_catalog.pg_tables t
   WHERE  schemaname NOT LIKE 'pg\_%'     -- exclude system schemas
   AND    tablename LIKE 'prefix' || '%'  -- your table name prefix
   );
END
$do$;

相关:

Is there a postgres command to list/drop all materialized views?

在最后一个示例中使用方便安装的系统目录pg_tables。和format() 为方便起见。见:

How to check if a table exists in a given schema Table name as a PostgreSQL function parameter

【讨论】:

效果很好!!谢谢欧文。 嗯,我实际上可以在输出中看到 DROP TABLE 语句,但表并没有被删除。表格仍然存在并包含数据。使用第一个版本。 @Xb74Dkjb: CASCADE 一直存在,与第 12 页无关。它强制删除包括所有依赖对象,否则会被禁止。【参考方案3】:

假设前缀是'sales_'

第一步:获取所有带有该前缀的表名

SELECT table_name
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME LIKE 'sales_%';

第 2 步:点击“下载为 CSV”按钮。

第 3 步: 在编辑器中打开文件并将 "sales_ 替换为 ,sales" 有一个空格

第 4 步: DROP TABLE sales_regist, sales_name, sales_info, sales_somthing;

【讨论】:

以上是关于在 postgres 中删除所有共享相同前缀的表的主要内容,如果未能解决你的问题,请参考以下文章

python 批量删除mysql前缀相同的表

如何从给定数据库中删除所有带有前缀“bkp”的表?

Postgres - 级联删除不起作用

连接多个具有相同前缀名称的表

如何在 postgres 中删除特定模式中的每个表?

在 postgres 中更新具有大量删除的表的主键序列