Sig*_*Sig 142 postgresql truncate dynamic-sql plpgsql database-table
我经常需要在重建之前删除PostgreSQL数据库中的所有数据.我将如何直接在SQL中执行此操作?
目前我已经设法提出一个SQL语句,它返回我需要执行的所有命令:
SELECT 'TRUNCATE TABLE ' || tablename || ';' FROM pg_tables WHERE tableowner='MYUSER';
Run Code Online (Sandbox Code Playgroud)
但是,一旦拥有它们,我就无法以编程方式执行它们.
Hen*_*ing 206
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;
Run Code Online (Sandbox Code Playgroud)
这会创建一个存储的函数(您只需要执行一次),然后您可以像这样使用它:
SELECT truncate_tables('MYUSER');
Run Code Online (Sandbox Code Playgroud)
Erw*_*ter 86
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;
Run Code Online (Sandbox Code Playgroud)
format()
需要Postgres 9.1或更高版本.在旧版本中连接查询字符串,如下所示:
'TRUNCATE TABLE ' || quote_ident(_sch) || '.' || quote_ident(_tbl) || ' CASCADE';
Run Code Online (Sandbox Code Playgroud)
由于我们可以同时使用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;
Run Code Online (Sandbox Code Playgroud)
呼叫:
SELECT truncate_tables('postgres');
Run Code Online (Sandbox Code Playgroud)
你甚至不需要一个功能.在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$;
Run Code Online (Sandbox Code Playgroud)
关于和之间的区别pg_class
,pg_tables
和information_schema.tables
:
关于regclass
和引用表名:
my_template
用你的vanilla结构和所有空表创建一个"模板"数据库(让它命名)可能更简单,也更快.然后经过一个DROP
/CREATE DATABASE
周期:
DROP DATABASE mydb;
CREATE DATABASE mydb TEMPLATE my_template;
Run Code Online (Sandbox Code Playgroud)
这非常快,因为Postgres在文件级别复制整个结构.没有并发问题或其他开销会降低您的速度.
San*_*ing 35
如果我必须这样做,我将只创建一个当前db的模式sql,然后删除并创建db,然后使用schema sql加载db.
以下是涉及的步骤:
1)创建数据库的Schema转储(--schema-only
)
pg_dump mydb -s > schema.sql
2)删除数据库
drop database mydb;
3)创建数据库
create database mydb;
4)导入架构
psql mydb < schema.sql
只需执行下面的查询:
DO $$ DECLARE
r RECORD;
BEGIN
FOR r IN (SELECT tablename FROM pg_tables WHERE schemaname = current_schema()) LOOP
EXECUTE 'TRUNCATE TABLE ' || quote_ident(r.tablename) || '';
END LOOP;
END $$;
Run Code Online (Sandbox Code Playgroud)
我在这里没有看到的一件事是截断然后重置序列。请注意,像此处给出的所有内容一样的简单截断只会截断表,但会将序列保留为截断前的值。要在截断时将序列重置为其起始值,请执行以下操作:
TRUNCATE TABLE table_name RESTART IDENTITY CASCADE;
Run Code Online (Sandbox Code Playgroud)
您可以将 RESTART IDENTITY 添加到您喜欢的任何答案中,无需在此处重复。CASCADE 可以解决您可能面临的任何外键约束。
小智 7
简单地说,你可以运行这段 SQL :
DO $$ DECLARE
r RECORD;
BEGIN
FOR r IN (SELECT tablename FROM pg_tables WHERE schemaname =current_schema()) LOOP
EXECUTE 'TRUNCATE TABLE ' || quote_ident(r.tablename) || ' CASCADE';
END LOOP;
END $$;
Run Code Online (Sandbox Code Playgroud)
小智 5
伙计们,更好、更干净的方法是:
\n\n1) 创建数据库的架构转储 (--schema-only)\npg_dump mydb -s > schema.sql
\n\n2) 删除数据库\n删除数据库 mydb;
\n\n3) 创建数据库\n创建数据库mydb;
\n\n4) 导入架构\npsql mydb < schema.sql
\n\n它\xc2\xb4s 对我有用!
\n\n祝你有美好的一天。\n海勒姆·沃克
\n 归档时间: |
|
查看次数: |
132099 次 |
最近记录: |