Postgresql 截断表与外键约束

Clu*_*der 12 postgresql

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

我试过这样做

BEGIN; 
SET CONSTRAINTS ALL DEFERRED;
TRUNCATE tableA;
COMMIT;
Run Code Online (Sandbox Code Playgroud)

但收到错误

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.
Run Code Online (Sandbox Code Playgroud)

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

sha*_*fik 22

从一张表中删除所有数据

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

TRUNCATE TABLE table_name;
Run Code Online (Sandbox Code Playgroud)

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

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

TRUNCATE TABLE table_name CASCADE;
Run Code Online (Sandbox Code Playgroud)

更新:

BEGIN;
ALTER TABLE table_name DISABLE TRIGGER ALL;
TRUNCATE TABLE table_name;
ALTER TABLE table_name ENABLE TRIGGER ALL;
COMMIT;
Run Code Online (Sandbox Code Playgroud)

  • 据我了解,使用 CASCADE 也会影响相关表,这是我不想要的。我想通过忽略可能与其他表有关系的外键约束来截断表。 (6认同)
  • 更新是废话。禁用约束仅禁用对单行的约束检查,并且不会禁用执行无级联截断所需的约束本身。(根据定义截断,与 DELETE FROM 相反,不进行逐行处理,因此仅截断表 - 如果与级联一起使用,它甚至可以在现有约束下工作,因为它会截断所有依赖表)。因此,如果您编写“DELETE FROM TABLE table_name;”而不是“截断”,则更新将有效。 (4认同)
  • 如果您想这样做,请删除外键约束。 (2认同)
  • 您能详细说明一下您的最终更新吗?“禁用全部触发”的作用。似乎没有改变任何事情。 (2认同)

小智 5

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

  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
Run Code Online (Sandbox Code Playgroud)

重新创建脚本:

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;
Run Code Online (Sandbox Code Playgroud)


小智 5

您可以使用以下命令截断所有相关表

TRUNCATE TABLE table_1 , table_2 ,table_3 <等等...> ;