Je ne connais aucun moyen sûr et efficace de faire ce que vous voulez. Vous devez vraiment choisir si vous souhaitez définir les clés vous-même ou utiliser des clés générées et vous en tenir à une stratégie ou à l'autre.
Si la simultanéité ne vous dérange pas, vous pouvez LOCK TABLE thetable
, faites votre travail, setval
la séquence d'identifiant de la table à la prochaine valeur libre après ce que vous avez inséré, et commit
pour libérer le verrou. Cependant, cela causera toujours des problèmes avec les applications qui appellent explicitement nextval
(comme beaucoup d'ORM) plutôt que de laisser la base de données définir la valeur en l'omettant du ?INSERT
liste de colonnes ou en la nommant explicitement comme DEFAULT
.
Sinon, votre code (ou une fonction d'assistance PL/PgSQL) pourrait effectuer l'insertion dans une boucle de nouvelle tentative qui incrémente la clé et réessaye lorsqu'elle obtient une erreur d'intégrité. Cette stratégie ne fonctionnera pas si vous devez faire plus qu'une seule insertion par transaction. De plus dans SERIALIZABLE
mode d'isolation Je ne pense pas que vous puissiez le faire avec PL/PgSQL, vous devez utiliser une boucle de nouvelle tentative côté client pour gérer les échecs de sérialisation.
C'est une idée terrible. Utilisez les clés définies par l'application de manière cohérente ou les clés définies par la base de données de manière cohérente. Ne mélangez pas les deux.