web-dev-qa-db-fra.com

Comment valider toutes mes contraintes dans PostgreSQL?

Il semble que j'ai été mordu par le premier bogue décrit dans les notes de publication de PostgreSQL 9.3.4: http://www.postgresql.org/docs/devel/static/release-9-3-4. html

J'ai maintenant m. Dupliquer les clés primaires. Quelle est la meilleure approche pour faire une boucle de réacheminement de toutes mes contraintes (PKEYS, FKEYS) -> Problèmes de fixation -> Vérification encore, pour vous assurer que mes données sont correctes?

[~ # ~ ~] Mise à jour [~ # ~]

J'ai décidé d'accéder à une approche sur la correction de la question en supprimant toutes les contraintes, puis de les recréer à l'aide de la méthode suivante http://blog.hagander.net/archives/131-automatiquement-dropping-and-and-and- contraintes.html . Cependant, je suis actuellement coincé sur un message d'erreur, essayant de recréer un pkkey:

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)"

Qu'est-ce que cela signifie et comment puis-je résoudre celui-là (je peux vivre avec la supprimer, si c'est une option)?

Une autre question: mes données seraient-elles effectivement bonnes, si je viens de me débarrasser de toutes les lignes en double en les supprimant, puis a fait un pg_dump et a rétabli la base de données de cette décharge. Cela reconstruit la structure de données - non?

6
Niels Kristian

Eh bien, si vous avez besoin d'un moyen de vérifier si toutes les clés étrangères de votre table sont valides, cela pourrait aider (il valide simplement toutes les clés étrangères de votre schéma)

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;
$$;
7
druzin

Cela fonctionnera sur toutes les contraintes en toute sécurité.,

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';

Vous pouvez sauvegarder cela à un fichier et à un fichier Q/A ou d'exécuter tout cela à la fois si vous utilisez psql avec \gexec.

2
Evan Carroll

La solution proposée par Evan Carroll ne fonctionnait pas pour moi.

Je devais l'adapter à la marque avant toutes les contraintes qui ne sont pas valides.

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;
$$;
2
Maneki