PostgreSQL TRUNCATE TABLE

下面是一份 PostgreSQL TRUNCATE TABLE 命令完整参考手册,包含 语法、选项、实战示例、性能分析、权限要求、注意事项与最佳实践,适合开发、DBA 和架构师使用。


一、TRUNCATE 基本概念

TRUNCATE TABLE 是 PostgreSQL 中快速删除表中所有数据的命令,比 DELETE FROM table 快几十到上百倍

对比TRUNCATEDELETE
速度极快(元数据操作)慢(逐行删除 + 触发器)
是否触发触发器默认不触发触发
是否记录 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 权限
TRUNCATECASCADE所有相关表的 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 在事务中是安全的,适合数据迁移、测试环境清理。


七、性能对比(实测)

表行数DELETETRUNCATE加速比
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 tableTRUNCATE 权限GRANT TRUNCATE
sequence not restarted用了 CONTINUE IDENTITYRESTART 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 清空表


需要我提供一个 TRUNCATE 的 Python 脚本(支持安全备份 + 截断 + 重置序列)吗?

类似文章

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注