J'ai une situation où je dois appliquer une contrainte unique sur un ensemble de colonnes, mais seulement pour une valeur d'une colonne.
Donc, par exemple, j'ai une table comme Table (ID, Name, RecordStatus).
RecordStatus ne peut avoir qu'une valeur 1 ou 2 (active ou supprimée), et je veux créer une contrainte unique sur (ID, RecordStatus) uniquement lorsque RecordStatus = 1, car je m'en fiche s'il y a plusieurs enregistrements supprimés avec le même ID.
En plus d'écrire des déclencheurs, puis-je faire cela?
J'utilise SQL Server 2005.
sql
sql-server
sql-server-2005
np-dur
la source
la source
Réponses:
Ajoutez une contrainte de vérification comme celle-ci. La différence est que vous retournerez false si Status = 1 et Count> 0.
http://msdn.microsoft.com/en-us/library/ms188258.aspx
la source
Voici, l'index filtré . De la documentation (c'est moi qui souligne):
Et voici un exemple combinant un index unique avec un prédicat de filtre:
Ceci impose essentiellement l' unicité de
ID
quandRecordStatus
est1
.Suite à la création de cet index, une violation d'unicité soulèvera une arror:
Remarque: l'index filtré a été introduit dans SQL Server 2008. Pour les versions antérieures de SQL Server, veuillez consulter cette réponse .
la source
ansi_padding
des index filtrés, assurez-vous donc que cette option est activée en exécutantSET ANSI_PADDING ON
avant de créer un index filtré.Vous pouvez déplacer les enregistrements supprimés vers une table qui n'a pas la contrainte, et peut-être utiliser une vue avec UNION des deux tables pour conserver l'apparence d'une seule table.
la source
Vous pouvez le faire d'une manière vraiment pirate ...
Créez une vue schématique sur votre table.
CREATE VIEW Quel que soit SELECT * FROM Table WHERE RecordStatus = 1
Créez maintenant une contrainte unique sur la vue avec les champs souhaités.
Une note sur les vues schématisées cependant, si vous modifiez les tables sous-jacentes, vous devrez recréer la vue. Beaucoup de pièges à cause de cela.
la source
Parce que vous allez autoriser les doublons, une contrainte unique ne fonctionnera pas. Vous pouvez créer une contrainte de vérification pour la colonne RecordStatus et une procédure stockée pour INSERT qui vérifie les enregistrements actifs existants avant d'insérer des ID en double.
la source
Si vous ne pouvez pas utiliser NULL comme RecordStatus comme l'a suggéré Bill, vous pouvez combiner son idée avec un index basé sur une fonction. Créez une fonction qui renvoie NULL si RecordStatus n'est pas l'une des valeurs que vous souhaitez prendre en compte dans votre contrainte (et RecordStatus sinon) et créez un index sur cela.
Cela présente l'avantage de ne pas avoir à examiner explicitement les autres lignes de la table dans votre contrainte, ce qui peut entraîner des problèmes de performances.
Je devrais dire que je ne connais pas du tout le serveur SQL, mais j'ai utilisé avec succès cette approche dans Oracle.
la source