Supprimer la “valeur de clé en double viole la contrainte unique” erreurs
Je suis le développement de Rails 3 app qui utilise Postgresql comme base de données. J'ai le tableau ci-dessous:
Table "public.test"
Column | Type | Modifiers
---------------+---------+-----------
id | integer | not null
some_other_id | integer |
Indexes:
"test_pkey" PRIMARY KEY, btree (id)
"some_other_id_key" UNIQUE CONSTRAINT, btree (some_other_id)
Cela a deux colonnes:
- id, qui est la clé primaire (créé automatiquement par rails)
- some_other_id, qui contient les clés générées par un autre système. Cet id doit être unique, j'ai donc ajouté une contrainte de clé unique pour la table.
Maintenant, si j'essaie d'insérer une ligne avec un double some_other_id
, il ne parvient pas (bon) et j'obtiens le résultat suivant dans mon Postgres journaux:
ERROR: duplicate key value violates unique constraint "some_other_id_key"
Le problème est qu'il est totalement principale pour mon application pour essayer et ajouter le même ID à deux reprises, et mes journaux sont des envois en nombre avec ce message "ERREUR", ce qui provoque divers problèmes: les fichiers prennent beaucoup d'espace disque, les diagnostics se perdre dans le bruit, Postgres à jeter diags à conserver les fichiers journaux à l'intérieur des limites de taille, etc.
Personne ne sait comment je peux soit:
- Supprimer le journal, soit par la suppression de tous les journaux à propos de cette clé, ou peut-être en spécifiant quelque chose sur la transaction qui tente de faire le
INSERT
. - Utiliser un autre Postgres fonction de repérer le double de la clé et de ne pas essayer la
INSERT
. J'ai entendu des règles et des déclencheurs, mais je ne peux pas obtenir soit pour le travail (même si je ne suis pas Postgres expert).
Noter que toute solution doit travailler avec les Rails de, qui ne de son insère comme ceci:
INSERT INTO test (some_other_id) VALUES (123) RETURNING id;
BTW votre insertion
INSERT INTO test (some_other_id) VALUES (123) RETURNING id;
ne fournit pas une valeur de l'id (qui n'est PAS NULLE), il devrait donc aussi violer la contrainte not NULL une pièce d'identité. Avez-vous nous donner la vraie définition de la table? est l'id d'une série, par hasard?
OriginalL'auteur Alex Hockey | 2012-09-12
Vous devez vous connecter pour publier un commentaire.
Pour éviter le double de la clé d'erreur pour commencer:
Je suis en supposant que id est un série colonne qui reçoit sa valeur automatiquement.
Ceci est soumis à un de très petite race condition (dans l'intervalle de temps entre la
SELECT
et laINSERT
). Mais le pire qui puisse arriver est que vous obtenez un double de la clé d'erreur après tout, et ce sera presque jamais se produire et ne devrait pas être un problème dans votre cas.Vous pouvez toujours utiliser SQL brut si votre cadre restreint de vos options à utiliser la bonne syntaxe.
Ou vous pouvez créer un fichier UDF (user defined function) dans le but:
Appel:
Ou, à défaut, à un déjà existant
id
:Encore une fois, qui laisse un minimum de chances pour une condition de course. Vous pouvez éliminer ce au prix d'une moindre performance:
Rappelez-vous juste que vous obtenez une exception au lieu d'une
id
si la condition de la course des grèves avec la fonction plpgsql.OriginalL'auteur Erwin Brandstetter
Vous pouvez désactiver la journalisation des messages d'erreur pour la session (ou dans le monde, en fait), mais il nécessite des privilèges de superutilisateur:
En cours d'exécution:
seulement les erreurs fatales sont enregistrés jusqu'à ce que la session (=la connexion) est terminé ou vous délivrer un nouveau
set
déclaration de réinitialiser la valeur.Mais que seul un super-utilisateur est autorisé à modifier cela, il n'est probablement pas une bonne solution car il serait nécessaire de votre demande à l'utilisateur de disposer de ce privilège qui est un problème de sécurité majeur.
postgresql.conf
, mais le réglage il n'y a probablement une mauvaise idée que ça vous masque les messages importants concernant les problèmes de configuration, etc.ALTER USER my_rails_user SET log_min_messages = fatal;
peut-être moins drastique, mais peut encore les masques des messages importants. Mieux fixer votre application ne permet pas l'insertion de doublons.OriginalL'auteur a_horse_with_no_name
Si vous voulez simplement supprimer ces erreurs tout en travaillant dans
psql
, vous pouvez le fairequi va durer pour le reste de votre session.
OriginalL'auteur Randall