Comment puis-je définir une colonne dans PostgreSQL de telle sorte que chaque valeur doit être dans une séquence, et non pas la séquence que vous obtenez en utilisant le type serial
mais une telle qu'une valeur 2 ne peut être insérée que si une valeur 1 existe déjà dans la colonne ?
Réponses
Trop de publicités?J'ai écrit un exemple détaillé de la mise en œuvre d'une séquence sans faille en utilisant PL/PgSQL. aquí .
L'idée générale est que vous voulez une table pour stocker les valeurs de la séquence, et vous utilisez SELECT ... FOR UPDATE
suivi par UPDATE
- ou le raccourci UPDATE ... RETURNING
- pour en extraire des valeurs tout en verrouillant la ligne jusqu'à ce que votre transaction soit validée ou annulée.
En théorie, vous pourriez utiliser une contrainte qui fonctionnerait comme suit. (Mais cela ne fonctionnera pas en pratique).
- Comptez les rangs.
- Évaluer
max(column) - min(column) + 1
. - Comparez les résultats.
Vous devrez probablement insérer une ligne avant de créer la contrainte CHECK. Si vous ne le faites pas, max(column) renvoie NULL. Avec une ligne,
- Comptez les rangs (1).
- Évaluer
max(column) - min(column) + 1
. (1 - 1 + 1 = 1) - Comparez les résultats. (1 = 1)
Avec 10 rangs .
- Comptez les rangs (10).
- Évaluer
max(column) - min(column) + 1
. (10 - 1 + 1 = 10) - Comparez les résultats. (10 = 10)
Le fait que la séquence commence à 1 n'a pas d'importance ; cette façon de vérifier montrera toujours un vide s'il existe. Si vous aviez besoin de garantir que la séquence sans vide commence à 1, vous pourriez l'ajouter à la contrainte CHECK.
Pour autant que je sache, il n'y a aucun moyen de faire cela de manière déclarative avec les bases de données actuelles. Pour le faire, vous auriez besoin du support de CREATE ASSERTION
. (Mais je peux me tromper.) Dans PostgreSQL, je pense que votre seule chance d'y parvenir implique du code procédural dans plusieurs triggers AFTER.
Je n'ai qu'une seule table qui doit être sans espace. C'est une table de calendrier. Nous exécutons une requête une fois par nuit qui fait ces calculs, et elle me permet de savoir si j'ai un écart.