J'ai lu ceci à propos du mot-clé SQL DEFERRABLE
dans Database Systems - The Complete Book .
Le dernier [NOT DEFERRABLE] est la valeur par défaut, et signifie que chaque fois qu'une instruction de modification de base de données est exécutée, la contrainte est vérifiée immédiatement après, si la modification peut violer la contrainte de clé étrangère.
Cependant, si nous déclarons qu'une contrainte est DEFERRABLE , nous avons la possibilité de la faire attendre qu'une transaction soit terminée avant de vérifier la contrainte.
Nous suivons le mot-clé DEFERRABLE soit INITIALLY DEFERRED soit INITIALLY IMMEDIATE . Dans le premier cas, la vérification sera reportée juste avant la validation de chaque transaction. Dans ce dernier cas, le contrôle sera effectué immédiatement après chaque relevé.
En quoi est-ce NOT DEFERRABLE
différent de DEFERRABLE INITIALLY IMMEDIATE
? Dans les deux cas, il semble que toutes les contraintes sont vérifiées après chaque déclaration individuelle.
DEFERRABLE
indique l'intention du concepteur selon laquelle le report de la contrainte est une action valable ou nécessaire. Ce n'est pas le cas pour la grande majorité des contraintes de base de données et l'étiquetage du tout carDEFERRABLE
cela perdrait cette distinction utile.NOT DEFERRABLE
est généralement le plus rapide.Mis à part les autres réponses (correctes), quand on parle de PostgreSQL , il faut dire que:
avec NOT DEFERRABLE chaque ligne est vérifiée lors de l'insertion / mise à jour
avec DEFERRABLE (actuellement IMMEDIATE ) toutes les lignes sont vérifiées à la fin de l'insertion / mise à jour
avec DEFERRABLE (actuellement DEFERRED ) toutes les lignes sont vérifiées à la fin de la transaction
Il n'est donc pas correct de dire qu'une contrainte DEFERRABLE agit comme une contrainte NOT DEFERRABLE lorsqu'elle est définie sur IMMEDIATE.
Développons cette différence:
Cela génère correctement:
Mais si nous supprimons l'instruction DEFERRABLE INITIALLY IMMEDIATE,
ADDENDA (12 octobre 2017)
Ce comportement est en effet documenté ici , section "Compatibilité":
la source
NOT DEFERRABLE
est la vitesse ( voir ici , section Contraintes d'unicité non différées , «Sachez que cela peut être beaucoup plus lent que la vérification d'unicité immédiate» ).DEFERRABLE
contrainte ne peut pas être référencée en tant que clé étrangère dans d'autres tables ( voir ici , section Paramètres , "Les colonnes référencées doivent être les colonnes d'une contrainte de clé primaire ou unique non déferrable dans la table référencée" ).NOT DEFERRABLE
simplement parce qu'elle fonctionne mieux?NOT DEFERRABLE
2) si au moins un FK fait référence à la contrainte, nous utilisonsNOT DEFERRABLE
également 3) dans les autres cas, nous utilisonsDEFERRABLE INITIALLY IMMEDIATE
. Cela pourrait légèrement diminuer les performances de ces contraintes, mais assure une compatibilité maximale avec les autres SGBD que nous utilisons (Oracle, SqlServer). PK et FK ne sont pas un problème car nous ne mettons jamais à jour leurs valeurs (ce qui, je pense, est une bonne habitude de programmation pour les bases de données).Outre l'évidence de pouvoir différer, la différence réside en fait dans les performances. S'il n'y avait pas de pénalité de performance, il ne serait pas nécessaire d'avoir la possibilité de choisir de différer ou non - toutes les contraintes seraient simplement reportables.
La pénalité des performances est liée aux optimisations que la base de données peut effectuer étant donné la connaissance de la manière dont les données sont restreintes. Par exemple, l'index qui est créé pour sauvegarder une contrainte unique dans Oracle ne peut pas être un index unique si la contrainte est reportable, car l'autorisation temporaire des doublons doit être autorisée. Cependant, si la contrainte n'est pas reportable, l'index peut être unique.
la source
Je suis très en retard à la fête mais je voulais ajouter que - en décembre 2018 - seules deux bases de données que je connais (il y en a peut-être plus) offrent un certain niveau d'implémentation de cette fonctionnalité SQL standard :
* 1 Même si Oracle 12c accepte l'
NOT DEFERRABLE
état de contrainte , il l'ignore en fait et le fait fonctionner commeDEFERRABLE INITIALLY IMMEDIATE
.Comme vous le voyez, Oracle n'implémente pas le premier type (
NOT DEFERRABLE
), et c'est pourquoi les développeurs utilisant Oracle (l'OP dans ce cas) peuvent être confus et considérer les deux premiers types comme équivalents.Fait intéressant, Oracle et PostgreSQL ont un type par défaut différent. Cela a peut-être des implications sur les performances.
la source
NOT DEFERRABLE - vous ne pouvez pas modifier la vérification des contraintes, oracle la vérifie après chaque instruction (c'est-à-dire directement après l'instruction insert).
DEFERRABLE INITIALLY IMMEDIATE - oracle vérifie la contrainte après chaque instruction. MAIS, vous pouvez le changer après chaque transaction (c'est-à-dire après la validation):
la source