如何在 postgresql 中验证我的所有约束?

Nie*_*ian 7 postgresql foreign-key constraint primary-key postgresql-9.3

似乎我被 postgresql 9.3.4 的发行说明中描述的第一个错误所困扰:http : //www.postgresql.org/docs/devel/static/release-9-3-4.html

我现在有例如重复的主键。对所有约束(pkeys、fkeys)进行重新检查循环的最佳方法是什么 -> 修复问题 -> 再次检查以确保我的数据正常?

更新

我决定通过删除所有约束来解决问题,然后使用以下方法重新创建它们http://blog.hagander.net/archives/131-Automatically-dropping-and-creating-constraints.html。但是我目前被困在一条错误消息上,试图重新创建一个 pkey:

ERROR:  failed to find parent tuple for heap-only tuple at (1192248,5) in table "fruits"
CONTEXT:  SQL statement "ALTER TABLE "pm"."fruits" ADD CONSTRAINT "fruits_pkey" PRIMARY KEY (id)"
Run Code Online (Sandbox Code Playgroud)

这是什么意思,我该如何解决这个问题(如果可以的话,我可以忍受删除它)?

另一个问题:如果我只是通过删除重复行来摆脱它们,然后执行 pg_dump,并从该转储中恢复数据库,那么我的数据实际上是否一切正常。它会重建数据结构 - 对吗?

dru*_*zin 7

好吧,如果您需要一种方法来检查表中的所有外键是否有效,这可能会有所帮助(它只是验证架构中的所有外键)

do $$
  declare r record;
BEGIN 
FOR r IN  (
  SELECT FORMAT(
    'ALTER TABLE %I VALIDATE CONSTRAINT %I;',
    tc.table_name,
    tc.constraint_name
  ) AS x
  FROM information_schema.table_constraints AS tc  
  JOIN information_schema.tables t ON t.table_name = tc.table_name and t.table_type = 'BASE TABLE' 
  JOIN information_schema.key_column_usage AS kcu ON tc.constraint_name = kcu.constraint_name 
  JOIN information_schema.constraint_column_usage AS ccu ON ccu.constraint_name = tc.constraint_name 
  WHERE  constraint_type = 'FOREIGN KEY' 
    AND tc.constraint_schema = 'public'
)
  LOOP
    EXECUTE (r.x);  
  END LOOP;
END;
$$;
Run Code Online (Sandbox Code Playgroud)


Eva*_*oll 5

这将安全地适用于所有约束。,

SELECT FORMAT(
  'ALTER TABLE %I.%I.%I VALIDATE CONSTRAINT %I;',
  current_database(),
  nsp.nspname,
  cls.relname,
  con.conname
)                                         
FROM pg_constraint AS con
JOIN pg_class AS cls
  ON con.conrelid = cls.oid
JOIN pg_namespace AS nsp
  ON cls.relnamespace = nsp.oid
WHERE convalidated IS FALSE
  -- or delete it for all constraints in all schemas
  AND nsp.nspname = 'mySchema';
Run Code Online (Sandbox Code Playgroud)

您可以将其保存到文件中并对其进行问答,或者如果使用psqlwith则立即执行全部内容\gexec


小智 5

Evan Carroll提出的解决方案对我不起作用。

我不得不调整它以在所有约束之前标记为无效。

do $$
  declare r record;
BEGIN
FOR r IN  (
  SELECT FORMAT(
    'UPDATE pg_constraint SET convalidated=false WHERE conname = ''%I''; ALTER TABLE %I VALIDATE CONSTRAINT %I;',
    tc.constraint_name,
    tc.table_name,
    tc.constraint_name
  ) AS x
  FROM information_schema.table_constraints AS tc
  JOIN information_schema.tables t ON t.table_name = tc.table_name and t.table_type = 'BASE TABLE'
  JOIN information_schema.key_column_usage AS kcu ON tc.constraint_name = kcu.constraint_name
  JOIN information_schema.constraint_column_usage AS ccu ON ccu.constraint_name = tc.constraint_name
  WHERE  constraint_type = 'FOREIGN KEY'
    AND tc.constraint_schema = 'public'
)
  LOOP
    EXECUTE (r.x);
  END LOOP;
END;
$$;
Run Code Online (Sandbox Code Playgroud)