在 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 schemac.oid::regclass
如何防御 SQL 注入?
或在单个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()
为方便起见。见:
【讨论】:
效果很好!!谢谢欧文。 嗯,我实际上可以在输出中看到 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 中删除所有共享相同前缀的表的主要内容,如果未能解决你的问题,请参考以下文章