带有外键约束的PostgreSQL截断表

时间:2019-06-21 09:21:42

标签: python django postgresql

当前,我正在尝试截断在Postgresql 11.3上具有外键约束的表。

我尝试这样做

BEGIN; 
SET CONSTRAINTS ALL DEFERRED;
TRUNCATE tableA;
COMMIT;

但收到错误

ERROR:  cannot truncate a table referenced in a foreign key constraint
DETAIL:  Table "xxx" references "tableA".
HINT:  Truncate table "xxx" at the same time, or use TRUNCATE ... CASCADE.

SET CONSTRAINTS ALL DEFERRED会关闭外键约束检查吗?无论如何,有没有在不触发外键约束检查且不涉及CASCADE的情况下截断表?

3 个答案:

答案 0 :(得分:1)

您可以执行以下步骤以避免在截断期间出现外键错误

  1. 创建删除所有外键和约束(尚未运行)的自动化脚本

  2. 创建自动创建所有外键和约束的自动化脚本

  3. 运行放置脚本

  4. 正常运行TRUNCATE your_table

  5. 运行重新创建密钥脚本

通过这些步骤,由于没有外键,因此TRUNCATE命令可以正常运行。

拖放脚本和重新创建脚本取自https://blog.hagander.net/automatically-dropping-and-creating-constraints-131/

拖放脚本:

SELECT 'ALTER TABLE "'||nspname||'"."'||relname||'" DROP CONSTRAINT "'||conname||'";'
 FROM pg_constraint 
 INNER JOIN pg_class ON conrelid=pg_class.oid 
 INNER JOIN pg_namespace ON pg_namespace.oid=pg_class.relnamespace 
 ORDER BY CASE WHEN contype='f' THEN 0 ELSE 1 END,contype,nspname,relname,conname

重新创建脚本:

SELECT 'ALTER TABLE "'||nspname||'"."'||relname||'" ADD CONSTRAINT "'||conname||'" '||
   pg_get_constraintdef(pg_constraint.oid)||';'
 FROM pg_constraint
 INNER JOIN pg_class ON conrelid=pg_class.oid
 INNER JOIN pg_namespace ON pg_namespace.oid=pg_class.relnamespace
 ORDER BY CASE WHEN contype='f' THEN 0 ELSE 1 END DESC,contype DESC,nspname DESC,relname DESC,conname DESC;

答案 1 :(得分:0)

从一个表中删除所有数据

TRUNCATE TABLE语句的最简单形式如下:

TRUNCATE TABLE table_name;

从具有外键引用的表中删除所有数据

要从主表和具有主表外键引用的所有表中删除数据,请使用CASCADE选项,如下所示:

TRUNCATE TABLE table_name CASCADE;

更新

BEGIN;
ALTER TABLE table_name DISABLE TRIGGER ALL;
TRUNCATE TABLE table_name;
ALTER TABLE table_name ENABLE TRIGGER ALL;
COMMIT;

答案 2 :(得分:0)

我到这里结束是因为我的 Sqitch 数据还原脚本使用了TRUNCATE。一种可能不适合所有人的解决方法(但对我有用):

DELETE FROM tableA WHERE id IN (
  '5b50e44a-e8dd-4950-8708-588d6620d578',
  'd1857bfa-43bc-4284-8a49-c6ceba80a66f',
  '3ddff193-eb9f-495b-b63d-87b4e0637caa'
  --etc
);