Dans une gâchette dans ma base de données SQL-Server 2008, j'ai besoin de vérifier si une variable est exactement nulle. Ce code fait ce dont j'ai besoin, mais peut-il être fait en moins de lignes et plus lisible?
DECLARE @string varchar
DECLARE @float float
DECLARE @bit bit
DECLARE @int int
Set @string=NULL -- Exactly one of these variables needs to be set
Set @float=NULL --
Set @bit=NULL --
Set @int=NULL --
IF( (@string is not null AND COALESCE(@float, @bit, @int) IS NULL)
OR (@float is not null AND COALESCE(@string, @bit, @int) IS NULL)
OR (@bit is not null AND COALESCE(@string, @float, @int) IS NULL)
OR (@int is not null AND COALESCE(@string, @float, @bit) IS NULL)
)
print ' ok'
ELSE
print ' not ok'
6 Réponses :
J'ai trouvé une solution alternative mais ce n'est pas moins de lignes. Il utilise l'opérateur Bitwise Xor. Je ne sais pas si je l'aime ou non - mais cela signifie que chaque variable est uniquement vérifiée une fois que sur chaque ligne, elle satisfait également à votre condition de lisibilité:
DECLARE @string varchar
DECLARE @float float
DECLARE @bit bit
DECLARE @int int
SET @string=NULL -- Exactly one of these variables needs to be set
SET @float=NULL --
SET @bit=NULL --
SET @int=NULL --
if ((case when @string is null then 1 else 0 end)
^ (case when @float is null then 1 else 0 end)
^ (case when @bit is null then 1 else 0 end)
^ (case when @int is null then 1 else 0 end)) = 1
print 'ok'
else
print 'not ok'
Je ne suis pas nécessairement sûr qu'il est plus lisible (bien que je suppose que si vous l'avez abstraité à une fonction, cela pourrait être) mais est un peu plus flexible? p> p>
Je pensais être intelligent, mais cela ne fonctionnera que si aucun des 4 variables ne peut avoir exactement la même valeur, il n'est donc pas utile dans de nombreux cas. Je le posterai quand même:
IF( (COALESCE(@string,@float, @bit, @int) IS NULL) OR (COALESCE(@string, @float, @bit, @int) != COALESCE(@int, @bit, @float, @string)) ) print 'not ok' ELSE print 'ok'
Cette requête fonctionnera également dans des problèmes si la valeur de chaîne ne peut pas être convertie en un numéro.
SELECT CASE WHEN COUNT(c) =1 THEN 'Y' ELSE 'N' END FROM (VALUES (CAST(@string AS SQL_VARIANT)),(@float),(@bit),(@int)) T (c)
J'aime la brièveté de celui-ci. Voici un défi supplémentaire: cela peut-il être modifié afin qu'il puisse entrer dans une contrainte de contrôle?
Je vais marquer cela comme réponse à la question. Bien que la réponse de Damiens résout mon problème, je pense que c'est la réponse la plus courte à la question initiale.
Je pense que je connais le type de configuration que vous créez. Dans ces circonstances, je me définis habituellement des structures de données comme suit: Notez que j'ai fabriqué Maintenant, dans la table qui collecte les données: p> La deuxième contrainte de clé étrangère garantit que la colonne Type correspond au type défini pour la élément de données et la paire de contraintes de contrôle garantissent qu'une seule colonne (et la colonne de droite) n'est pas null. p> Si vous devez masquer la colonne Type des utilisateurs, je suggère de renommer le Tableau ci-dessus (par exemple, dataitemid, typentquiitée code> un surcharge, afin que je puisse y référer dans un étranger Contrainte clé. P> _Answers code>) Création d'une vue avec un déclencheur d'insertion: p>
Merci beaucoup. C'est une solution à mon problème, bien que ce ne soit pas la réponse à la question. ;-) Seule une chose que je trouve un peu disgracieuse à ce sujet consiste à enregistrer la colonne de type deux fois et à avoir les chaînes des types autorisés à deux endroits de mon code.
Ne pouvons-nous pas vérifier par ceci:
IF ISNULL(@string, '') <> ''
OR ISNULL(@float, 0) <> 0
OR @bit IS NOT NULL
OR ISNULL(@int, 0) <> 0
PRINT 'There is atleast one value'
ELSE
PRINT 'ALL ARE NULL'
J'ai un mauvais sentiment à ce sujet - je veux juste vérifier que vous êtes conscient qu'un déclencheur incendie pour toutes les lignes mises à jour par la déclaration. Donc, si vous avez quelque chose comme
SELECT @String = String, @FLOAT = Float ... à partir de l'inséré code>, votre déclencheur est déjà brisé en matière d'inserts / mises à jour / suppression / suppression.De plus, si cela consiste à garantir que l'intégrité de la table sous-jacente (et c'est le seul chèque requis), il serait préférable de mettre le prédicat que vous vous retrouvez dans une contrainte de contrôle plutôt qu'un déclencheur.
Merci, j'ai oublié plusieurs rangées. Doit regarder dans ça. La raison pour laquelle j'ai besoin d'un déclencheur est que je dois vérifier la contrainte contre une autre table, qui détermine le champ autorisé à être défini. Peut-être que je vais mettre la "une seule" condition dans une contrainte de contrôle et vérifier la table dans la gâchette.