【发布时间】:2011-05-11 06:28:16
【问题描述】:
使用分区时,通常需要一次删除所有分区。
然而
DROP TABLE tablename*
不起作用。 (不考虑通配符)。
有没有一种优雅的(阅读:容易记住)方法在一个带有通配符的命令中删除多个表?
【问题讨论】:
标签: sql postgresql
使用分区时,通常需要一次删除所有分区。
然而
DROP TABLE tablename*
不起作用。 (不考虑通配符)。
有没有一种优雅的(阅读:容易记住)方法在一个带有通配符的命令中删除多个表?
【问题讨论】:
标签: sql postgresql
使用逗号分隔列表:
DROP TABLE foo, bar, baz;
如果你真的需要一把足枪,这个就可以了:
CREATE OR REPLACE FUNCTION footgun(IN _schema TEXT, IN _parttionbase TEXT)
RETURNS void
LANGUAGE plpgsql
AS
$$
DECLARE
row record;
BEGIN
FOR row IN
SELECT
table_schema,
table_name
FROM
information_schema.tables
WHERE
table_type = 'BASE TABLE'
AND
table_schema = _schema
AND
table_name ILIKE (_parttionbase || '%')
LOOP
EXECUTE 'DROP TABLE ' || quote_ident(row.table_schema) || '.' || quote_ident(row.table_name) || ' CASCADE ';
RAISE INFO 'Dropped table: %', quote_ident(row.table_schema) || '.' || quote_ident(row.table_name);
END LOOP;
END;
$$;
SELECT footgun('public', 'tablename');
【讨论】:
|| ' CASCADE ';,它是完美的
这是这个问题的另一个 hackish 答案。它适用于ubuntu,也许也适用于其他一些操作系统。在 postgres 命令提示符中执行 \dt(在我的情况下,命令提示符在 genome-terminal 中运行)。然后你会在终端中看到很多表格。现在使用genome-terminal 的ctrl+click-drag 功能复制所有表的名称。 Open python,做一些字符串处理(用''替换'',然后用','替换'\n'),你会得到所有表的逗号分隔列表。现在在 psql shell 中执行drop table CTRL+SHIFT+V 就完成了。我知道这太具体了,我只想分享。 :)
【讨论】:
DROP TABLE whatever_然后按TAB,将所有表格复制到剪贴板,打开sublime,查找/替换,用正则表达式替换,\s+为, 并粘贴到终端上。
\e 从 psql 跳转到您的编辑器,复制您的列表并放置逗号。
我用过这个。
echo "select 'drop table '||tablename||';' from pg_tables where tablename like 'name%'" | \
psql -U postgres -d dbname -t | \
psql -U postgres -d dbname
用适当的值替换dbname 和name%。
【讨论】:
我一直觉得创建一个我可以在运行之前查看和测试的 sql 脚本比依赖于让 plpgsql 恰到好处,这样它就不会破坏我的数据库更舒服。 bash 中的一些简单操作从目录中选择表名,然后为我创建 drop 语句。所以对于 8.4.x,你会得到这个基本查询:
SELECT 'drop table '||n.nspname ||'.'|| c.relname||';' as "Name"
FROM pg_catalog.pg_class c
LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
WHERE c.relkind IN ('r','v','S','')
AND n.nspname <> 'pg_catalog'
AND n.nspname <> 'information_schema'
AND n.nspname !~ '^pg_toast'
AND pg_catalog.pg_table_is_visible(c.oid);
您可以在其中添加 where 子句。 (where c.relname ilike 'bubba%')
输出如下所示:
Name
-----------------------
drop table public.a1;
drop table public.a2;
因此,将其保存到 .sql 文件并使用 psql -f filename.sql 运行它
【讨论】:
relkind = 'S') 生成一个drop table 命令。序列上的drop table 将失败。相反,从relkind IN 子句中删除'S'。如果您需要删除序列,请使用常量数据select 'drop sequence' 构造一个类似的查询,这次使用c.relkind = 'S'
披露:此答案适用于 Linux 用户。
我会在@prongs 所说的内容中添加一些更具体的说明:
\dt 可以支持通配符:例如,您可以运行 \dt myPrefix* 以仅选择要删除的表;CTRL-SHIFT-DRAG 之后选择然后CTRL-SHIFT-C 复制文本;vim 中,转到INSERT MODE 并粘贴带有CTRL-SHIFT-V 的表格;ESC,然后运行:%s/[ ]*\n/, /g将其转换为逗号分隔列表,然后您可以将它(不包括最后一个逗号)粘贴到DROP TABLE % CASCADE中。【讨论】:
使用linux命令行工具,可以这样实现:
psql -d mydb -P tuples_only=1 -c '\dt' | cut -d '|' -f 2 | paste -sd "," | sed 's/ //g' | xargs -I{} echo psql -d mydb -c "drop table {};"
注意:最后一个回显在那里,因为我找不到在 drop 命令周围加上引号的方法,所以您需要复制并粘贴输出并自己添加引号。
如果有人能解决这个小问题,那就太棒了。
【讨论】:
所以我今天遇到了这个问题。我通过 pgadmin3 加载了我的服务器数据库并这样做了。表格按字母顺序排序,因此 shift 和 click 然后删除效果很好。
【讨论】:
我喜欢来自@Frank Heikens 的the answer。感谢那。无论如何,我想改进一点;
假设我们的分区表名称是partitioned_table,并且我们有一个数字后缀,我们每次都会增加它。喜欢partitioned_table_00,partitioned_table_01 ... partitioned_table_99
CREATE OR REPLACE drop_old_partitioned_tables(schema_name TEXT, partitioned_table_name TEXT, suffix TEXT)
RETURNS TEXT
LANGUAGE plpgsql
AS
$$
DECLARE
drop_query text;
BEGIN
SELECT 'DROP TABLE IF EXISTS ' || string_agg(format('%I.%I', table_schema, table_name), ', ')
INTO drop_query
FROM information_schema.tables
WHERE table_type = 'BASE TABLE'
AND table_schema = schema_name
AND table_name <= CONCAT(partitioned_table_name, '_', suffix) -- It will also drop the table which equals the given suffix
AND table_name ~ CONCAT(partitioned_table_name, '_\d{2}');
IF drop_query IS NULL THEN
RETURN 'There is no table to drop!';
ELSE
EXECUTE drop_query;
RETURN CONCAT('Executed query: ', (drop_query));
END IF;
END;
$$;
对于执行,您可以运行以下代码;
SELECT drop_old_partitioned_tables('public', 'partitioned_table', '10')
顺便说一句,如果您想对表进行每年分区,则表后缀应为年份,例如 partitioned_table_2021。即使您的数据更大而无法每年进行分区,您也可以像partitioned_table_2021_01 那样每月进行一次。不要忘记根据需要调整代码。
【讨论】:
感谢 Jon 的另一个解决方案:
tables=`psql -d DBNAME -P tuples_only=1 -c '\dt' |awk -F" " '/table_pattern/ {print $3","}'`
psql -d DBNAME -c "DROP TABLE ${tables%?};";
【讨论】: