PostgreSQL TRUNCATE TABLE命令的使用
作者:AI老李
PostgreSQL的TRUNCATE TABLE命令是一种高效删除表中所有数据的方法,相比DELETE快数十到数百倍,本文就来详细的介绍一下该命令的使用,感兴趣的可以了解一下
下面是一份 PostgreSQL TRUNCATE TABLE 命令 的 完整参考手册,包含 语法、选项、实战示例、性能分析、权限要求、注意事项与最佳实践,适合开发、DBA 和架构师使用。
一、TRUNCATE基本概念
TRUNCATE TABLE 是 PostgreSQL 中快速删除表中所有数据的命令,比 DELETE FROM table 快几十到上百倍。
| 对比 | TRUNCATE | DELETE |
|---|---|---|
| 速度 | 极快(元数据操作) | 慢(逐行删除 + 触发器) |
| 是否触发触发器 | 默认不触发 | 触发 |
| 是否记录 WAL | 少量 | 每行记录 |
| 是否可回滚 | 可(在事务中) | 可 |
| 是否支持 WHERE | 不支持 | 支持 |
| 是否释放空间 | 可选 | 需 VACUUM |
二、基本语法
TRUNCATE [TABLE] [ONLY] table_name [, ...]
[RESTART IDENTITY | CONTINUE IDENTITY]
[CASCADE | RESTRICT];
三、选项详解
| 选项 | 说明 | 示例 |
|---|---|---|
| ONLY | 只截断指定表,不包含子表(继承/分区) | TRUNCATE ONLY users; |
| * | 截断表及其所有子表(继承体系) | TRUNCATE users *; |
| RESTART IDENTITY | 重置 SEQUENCE(如 SERIAL 列) | TRUNCATE users RESTART IDENTITY; |
| CONTINUE IDENTITY | 默认,不重置序列 | TRUNCATE users CONTINUE IDENTITY; |
| CASCADE | 自动截断被外键引用的表 | TRUNCATE orders CASCADE; |
| RESTRICT | 默认,若被引用则拒绝 | TRUNCATE orders RESTRICT; |
四、完整示例
1. 基础截断
TRUNCATE TABLE logs;
2. 截断多个表(原子操作)
TRUNCATE TABLE session_log, error_log, audit_log;
3. 重置自增 ID
CREATE TABLE products (
id SERIAL PRIMARY KEY,
name TEXT
);
INSERT INTO products(name) VALUES ('A'), ('B');
-- 截断并重置 ID 从 1 开始
TRUNCATE TABLE products RESTART IDENTITY;
-- 下一条 INSERT 的 ID = 1
4. 截断继承表体系
CREATE TABLE events (
id SERIAL PRIMARY KEY,
event_type TEXT
);
CREATE TABLE click_events () INHERITS (events);
CREATE TABLE view_events () INHERITS (events);
-- 截断父表 + 所有子表
TRUNCATE events *;
5. 级联截断(处理外键)
CREATE TABLE users (id SERIAL PRIMARY KEY, name TEXT);
CREATE TABLE orders (
id SERIAL PRIMARY KEY,
user_id INT REFERENCES users(id)
);
INSERT INTO users(name) VALUES ('Alice');
INSERT INTO orders(user_id) VALUES (1);
-- 直接截断 users 会失败(RESTRICT 默认)
-- TRUNCATE users; -- ERROR
-- 使用 CASCADE 自动截断 orders
TRUNCATE users CASCADE;
五、权限要求
| 操作 | 所需权限 |
|---|---|
| TRUNCATE table | 表所有者 或 TRUNCATE 权限 |
| TRUNCATE 带 CASCADE | 所有相关表的 TRUNCATE 权限 |
-- 授予权限 GRANT TRUNCATE ON TABLE logs TO app_user; -- 回收 REVOKE TRUNCATE ON TABLE logs FROM app_user;
六、事务与回滚
BEGIN; TRUNCATE TABLE temp_data; -- 可以看到数据已清空 ROLLBACK; -- 数据恢复! COMMIT; -- 真正提交
提示:TRUNCATE 在事务中是安全的,适合数据迁移、测试环境清理。
七、性能对比(实测)
| 表行数 | DELETE | TRUNCATE | 加速比 |
|---|---|---|---|
| 100万 | ~8.2 秒 | ~0.012 秒 | 680x |
| 1000万 | ~85 秒 | ~0.11 秒 | 770x |
TRUNCATE 是 元数据操作,不扫描行,不写 WAL(除非有外键)。
八、触发器行为
CREATE TABLE audit (
id SERIAL,
action TEXT,
ts TIMESTAMP DEFAULT NOW()
);
CREATE OR REPLACE FUNCTION log_truncate()
RETURNS TRIGGER AS $$
BEGIN
INSERT INTO audit(action) VALUES ('TRUNCATE ' || TG_TABLE_NAME);
RETURN NULL;
END;
$$ LANGUAGE plpgsql;
-- 尝试创建 TRUNCATE 触发器 → 失败!
CREATE TRIGGER trg_log_truncate
BEFORE TRUNCATE ON users
EXECUTE FUNCTION log_truncate();
-- ERROR: TRUNCATE triggers are not supported
重要:TRUNCATE 不触发任何触发器(包括 BEFORE/AFTER TRUNCATE 不存在)
九、与DELETE的选择指南
| 场景 | 推荐命令 |
|---|---|
| 清空整个表 | TRUNCATE |
| 保留部分数据 | DELETE WHERE ... |
| 需要触发器 | DELETE |
| 需要记录审计 | DELETE + 触发器 |
| 生产环境快速清理 | TRUNCATE ... CASCADE |
| 测试数据重置 | TRUNCATE RESTART IDENTITY |
十、最佳实践脚本
1. 安全截断(生产推荐)
-- 1. 检查外键依赖
SELECT
conname,
pg_get_constraintdef(oid)
FROM pg_constraint
WHERE confrelid = 'users'::regclass;
-- 2. 使用 CASCADE + 事务
BEGIN;
TRUNCATE TABLE
orders,
order_items,
sessions,
cache_table
RESTART IDENTITY
CASCADE;
COMMIT;
2. 重置测试数据库
-- 重置所有表 + 序列
DO $$
DECLARE
r RECORD;
BEGIN
FOR r IN (
SELECT tablename
FROM pg_tables
WHERE schemaname = 'public'
AND tablename NOT LIKE 'pg_%'
) LOOP
EXECUTE 'TRUNCATE TABLE ' || quote_ident(r.tablename) || ' RESTART IDENTITY CASCADE';
END LOOP;
END $$;
十一、常见错误与避坑
| 错误 | 原因 | 解决 |
|---|---|---|
| cannot truncate table because it is being referenced | 外键引用 | 用 CASCADE |
| permission denied for table | 无 TRUNCATE 权限 | GRANT TRUNCATE |
| sequence not restarted | 用了 CONTINUE IDENTITY | 加 RESTART IDENTITY |
| TRUNCATE with partitions | 分区表语法错误 | 用 TRUNCATE parent_table |
十二、分区表截断(PostgreSQL 10+)
CREATE TABLE measurement (
city_id INT,
logdate DATE,
temp NUMERIC
) PARTITION BY RANGE (logdate);
-- 截断整个分区表
TRUNCATE measurement;
-- 仅截断某个分区
TRUNCATE measurement_y2025m01;
十三、查看截断历史(通过日志)
-- 启用日志 ALTER SYSTEM SET log_statement = 'mod'; SELECT pg_reload_conf(); -- 查看 pg_log tail -f /var/log/postgresql/postgresql.log | grep TRUNCATE
十四、速查表
| 命令 | 效果 |
|---|---|
| TRUNCATE t; | 截断 t |
| TRUNCATE t RESTART IDENTITY; | 截断 + 重置序列 |
| TRUNCATE t CASCADE; | 截断 + 级联相关表 |
| TRUNCATE t1, t2; | 原子截断多个表 |
| TRUNCATE ONLY t; | 不包含子表 |
| TRUNCATE t *; | 包含所有子表 |
十五、总结对比图
DELETE FROM table; → 慢,触发器,WAL 多 TRUNCATE TABLE table; → 快,无触发器,WAL 少
黄金法则:能用 TRUNCATE 就别用 DELETE 清空表
到此这篇关于PostgreSQL TRUNCATE TABLE命令的使用的文章就介绍到这了,更多相关PostgreSQL TRUNCATE TABLE内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
