Answers:
FrustratedWithFormsDesigner是正确的,PL / pgSQL可以做到这一点。这是脚本:
CREATE OR REPLACE FUNCTION truncate_tables(username IN VARCHAR) RETURNS void AS $$
DECLARE
statements CURSOR FOR
SELECT tablename FROM pg_tables
WHERE tableowner = username AND schemaname = 'public';
BEGIN
FOR stmt IN statements LOOP
EXECUTE 'TRUNCATE TABLE ' || quote_ident(stmt.tablename) || ' CASCADE;';
END LOOP;
END;
$$ LANGUAGE plpgsql;
这将创建一个存储的函数(您只需执行一次),然后可以像下面这样使用:
SELECT truncate_tables('MYUSER');
DECLARE r RECORD;
然后循环: FOR r IN SELECT tablename FROM pg_tables LOOP
在plpgsql中很少需要显式游标。使用更简单,更快的循环隐式游标FOR
:
注意:由于表名在每个数据库中都不唯一,因此必须对表名进行模式限定。另外,我将功能限制为默认模式“ public”。适应您的需求,但请确保排除系统架构pg_*
和information_schema
。
这些功能要非常小心。他们破坏您的数据库。我添加了儿童安全装置。评论RAISE NOTICE
界线并取消评论EXECUTE
以准备炸弹...
CREATE OR REPLACE FUNCTION f_truncate_tables(_username text)
RETURNS void AS
$func$
DECLARE
_tbl text;
_sch text;
BEGIN
FOR _sch, _tbl IN
SELECT schemaname, tablename
FROM pg_tables
WHERE tableowner = _username
AND schemaname = 'public'
LOOP
RAISE NOTICE '%',
-- EXECUTE -- dangerous, test before you execute!
format('TRUNCATE TABLE %I.%I CASCADE', _sch, _tbl);
END LOOP;
END
$func$ LANGUAGE plpgsql;
format()
需要Postgres 9.1或更高版本。在旧版本中,将查询字符串连接起来,如下所示:
'TRUNCATE TABLE ' || quote_ident(_sch) || '.' || quote_ident(_tbl) || ' CASCADE';
由于我们可以TRUNCATE
一次创建多个表,因此根本不需要任何游标或循环:
汇总所有表名并执行一条语句。更简单,更快:
CREATE OR REPLACE FUNCTION f_truncate_tables(_username text)
RETURNS void AS
$func$
BEGIN
RAISE NOTICE '%',
-- EXECUTE -- dangerous, test before you execute!
(SELECT 'TRUNCATE TABLE '
|| string_agg(format('%I.%I', schemaname, tablename), ', ')
|| ' CASCADE'
FROM pg_tables
WHERE tableowner = _username
AND schemaname = 'public'
);
END
$func$ LANGUAGE plpgsql;
呼叫:
SELECT truncate_tables('postgres');
您甚至不需要功能。在Postgres 9.0+中,您可以在DO
语句中执行动态命令。在Postgres 9.5+中,语法可以更简单:
DO
$func$
BEGIN
RAISE NOTICE '%',
-- EXECUTE
(SELECT 'TRUNCATE TABLE ' || string_agg(oid::regclass::text, ', ') || ' CASCADE'
FROM pg_class
WHERE relkind = 'r' -- only tables
AND relnamespace = 'public'::regnamespace
);
END
$func$;
关于之间的差异pg_class
,pg_tables
以及information_schema.tables
:
关于regclass
和引用表名:
使用您的香草结构和所有空表创建一个“模板”数据库(命名为my_template
)。然后经历一个DROP
/CREATE DATABASE
循环:
DROP DATABASE mydb;
CREATE DATABASE mydb TEMPLATE my_template;
这非常快,因为Postgres在文件级别复制整个结构。没有并发问题或其他开销使您慢下来。
如果并发连接使您无法删除数据库,请考虑:
DROP DATABASE mydb
显然,除外)。您是否将架构与数据库混淆了?
DO
指令(像任何其他SQL语句)在当前数据库中执行独占。Postgres无法在同一事务中访问其他数据库。您必须使用dblink或FDW来执行此操作。但这确实会影响当前数据库中的所有架构-除非您添加WHERE t.schemaname = 'public'
以在这种特定情况下将效果限制为一个特定架构。
您可以使用动态SQL依次执行每个语句吗?您可能必须编写一个PL / pgSQL脚本才能执行此操作。
http://www.postgresql.org/docs/8.3/static/plpgsql-statements.html(第38.5.4节:执行动态命令)
您也可以使用bash进行此操作:
#!/bin/bash
PGPASSWORD='' psql -h 127.0.0.1 -Upostgres sng --tuples-only --command "SELECT 'TRUNCATE TABLE ' || schemaname || '.' || tablename || ';' FROM pg_tables WHERE schemaname in ('cms_test', 'ids_test', 'logs_test', 'sps_test');" |
tr "\\n" " " |
xargs -I{} psql -h 127.0.0.1 -Upostgres sng --command "{}"
您将需要调整架构名称,密码和用户名以匹配您的架构。
清洁AUTO_INCREMENT
版本:
CREATE OR REPLACE FUNCTION truncate_tables(username IN VARCHAR) RETURNS void AS $$
DECLARE
statements CURSOR FOR
SELECT tablename FROM pg_tables
WHERE tableowner = username AND schemaname = 'public';
BEGIN
FOR stmt IN statements LOOP
EXECUTE 'TRUNCATE TABLE ' || quote_ident(stmt.tablename) || ' CASCADE;';
IF EXISTS (
SELECT column_name
FROM information_schema.columns
WHERE table_name=quote_ident(stmt.tablename) and column_name='id'
) THEN
EXECUTE 'ALTER SEQUENCE ' || quote_ident(stmt.tablename) || '_id_seq RESTART WITH 1';
END IF;
END LOOP;
END;
$$ LANGUAGE plpgsql;
如果可以使用psql,则可以使用\gexec
meta命令执行查询输出。
SELECT
format('TRUNCATE TABLE %I.%I', ns.nspname, c.relname)
FROM pg_namespace ns
JOIN pg_class c ON ns.oid = c.relnamespace
JOIN pg_roles r ON r.oid = c.relowner
WHERE
ns.nspname = 'table schema' AND -- add table schema criteria
r.rolname = 'table owner' AND -- add table owner criteria
ns.nspname NOT IN ('pg_catalog', 'information_schema') AND -- exclude system schemas
c.relkind = 'r' AND -- tables only
has_table_privilege(c.oid, 'TRUNCATE') -- check current user has truncate privilege
\gexec
请注意,\gexec
已引入9.6版