J'ai ce message d'erreur:
Msg 8134, niveau 16, état 1, ligne 1 Diviser par zéro erreur rencontrée.
Quelle est la meilleure façon d'écrire du code SQL pour que je ne revoie plus jamais ce message d'erreur?
Je pourrais effectuer l'une des opérations suivantes:
- Ajouter une clause where pour que mon diviseur ne soit jamais nul
Ou
- Je pourrais ajouter un énoncé de cas, afin qu'il y ait un traitement spécial pour zéro.
Est-ce la meilleure façon d'utiliser une NULLIF
clause?
Y a-t-il une meilleure façon, ou comment cela peut-il être appliqué?
sql
sql-server
sql-server-2005
sql-server-2008
Henrik Staun Poulsen
la source
la source
Réponses:
Afin d'éviter une erreur de "Division par zéro" nous l'avons programmée comme ceci:
Mais voici une manière beaucoup plus agréable de le faire:
Maintenant, le seul problème est de se souvenir du bit NullIf, si j'utilise la touche "/".
la source
IsNull
au lieu deNullIf
? Essayez-le vous-même!SELECT Value,1/NullIf(Value,0)FROM(VALUES(0),(5.0),(NULL))x(Value);
À moins que par "pauses" vous voulez dire renvoie un NULL? Vous pouvez le convertir en ce que vous voulez avecIsNull
ouCoalesce
.SELECT 1 / NULLIF(NULL, 0)
échoue, mais c'est parce qu'il aNULLIF()
besoin de connaître le type de données du premier argument. Cet exemple modifié fonctionne très bien:SELECT 1 / NULLIF(CAST(NULL AS INT), 0)
. Dans la vie réelle, vous allez fournir une colonne de tableNULLIF()
plutôt qu'uneNULL
constante. Comme les colonnes de table ont connu des types de données, cela fonctionne aussi très bien:SELECT 1 / NULLIF(SomeNullableColumn, 0) FROM SomeTable
.Dans le cas où vous souhaitez retourner zéro, dans le cas où une déviation zéro se produirait, vous pouvez utiliser:
Pour chaque diviseur qui est nul, vous obtiendrez un zéro dans le jeu de résultats.
la source
Cela semblait être la meilleure solution pour ma situation lorsque j'essayais de résoudre le problème de la division par zéro, ce qui se produit dans mes données.
Supposons que vous vouliez calculer les ratios hommes-femmes pour divers clubs scolaires, mais vous découvrez que la requête suivante échoue et génère une erreur de division par zéro lorsqu'il essaie de calculer le ratio pour le Lord of the Rings Club, qui n'a pas de femmes :
Vous pouvez utiliser la fonction
NULLIF
pour éviter la division par zéro.NULLIF
compare deux expressions et renvoie null si elles sont égales ou la première expression sinon.Réécrivez la requête comme suit:
Tout nombre divisé par
NULL
donneNULL
et aucune erreur n'est générée.la source
select males/(males+females), females/(males+females)
. Cela vous donnera la répartition en pourcentage des hommes et des femmes dans un club, comme 31% d'hommes, 69% de femmes.Vous pouvez également le faire au début de la requête:
Donc, si vous avez quelque chose comme
100/0
ça, cela retournera NULL. Je n'ai fait cela que pour des requêtes simples, donc je ne sais pas comment cela affectera les plus longues / complexes.la source
Vous pouvez au moins empêcher la requête de se rompre avec une erreur et retourner
NULL
s'il y a une division par zéro:Cependant, je ne convertirais JAMAIS cela en zéro avec
coalesce
comme cela est montré dans cette autre réponse qui a reçu de nombreuses augmentations. C'est complètement faux au sens mathématique, et c'est même dangereux car votre application retournera probablement des résultats faux et trompeurs.la source
EDIT: Je reçois beaucoup de downvotes récemment ... alors j'ai pensé que j'ajouterais simplement que cette réponse a été écrite avant que la question ne subisse sa dernière modification, où le retour de null était mis en surbrillance en option .. .qui semble très acceptable. Une partie de ma réponse s'adressait à des préoccupations comme celle d'Edwardo, dans les commentaires, qui semblait préconiser le retour d'un 0. C'est le cas contre lequel je me plaignais.
RÉPONSE: Je pense qu'il y a un problème sous-jacent ici, c'est que la division par 0 n'est pas légale. C'est une indication que quelque chose ne va pas fondamentalement. Si vous divisez par zéro, vous essayez de faire quelque chose qui n'a pas de sens mathématique, donc aucune réponse numérique que vous pouvez obtenir ne sera valide. (L'utilisation de null dans ce cas est raisonnable, car ce n'est pas une valeur qui sera utilisée dans des calculs mathématiques ultérieurs).
Edwardo demande donc dans les commentaires "et si l'utilisateur met un 0?", Et il préconise que ce soit correct d'obtenir un 0 en retour. Si l'utilisateur met zéro dans le montant et que vous voulez que 0 soit renvoyé lorsqu'il le fait, alors vous devez mettre du code au niveau des règles métier pour attraper cette valeur et retourner 0 ... pas de cas particulier où la division par 0 = 0.
C'est une différence subtile, mais c'est important ... parce que la prochaine fois que quelqu'un appelle votre fonction et s'attend à ce qu'elle fasse la bonne chose, et elle fait quelque chose de génial qui n'est pas mathématiquement correct, mais qui gère simplement le cas de bord particulier, il a un bonne chance de mordre quelqu'un plus tard. Vous ne divisez pas vraiment par 0 ... vous retournez simplement une mauvaise réponse à une mauvaise question.
Imaginez que je code quelque chose et je le foirais. Je devrais lire une valeur d'échelle de mesure de rayonnement, mais dans un cas de bord étrange que je n'avais pas prévu, j'ai lu 0. Je laisse ensuite ma valeur dans votre fonction ... vous me renvoyez un 0! Vive, pas de rayonnement! Sauf que c'est vraiment là et c'est juste que je passais dans une mauvaise valeur ... mais je n'en ai aucune idée. Je veux que la division lance l'erreur parce que c'est le drapeau que quelque chose ne va pas.
la source
En attrapant le zéro avec un nullif (), puis le null résultant avec un isnull (), vous pouvez contourner votre division par une erreur de zéro.
la source
Remplacer "diviser par zéro" par zéro est controversé - mais ce n'est pas non plus la seule option. Dans certains cas, le remplacement par 1 est (raisonnablement) approprié. Je me retrouve souvent à utiliser
quand je regarde les changements dans les scores / comptes, et que je veux par défaut à 1 si je n'ai pas de données. Par exemple
Plus souvent qu'autrement, j'ai en fait calculé ce rapport ailleurs (notamment parce qu'il peut générer des facteurs d'ajustement très importants pour les petits dénominateurs. Dans ce cas, je contrôlerais normalement que OldSampleScore est supérieur à un seuil; ce qui exclut alors zéro Mais parfois, le «hack» est approprié.
la source
J'ai écrit une fonction il y a quelque temps pour la gérer pour mes procédures stockées :
la source
Divisor
à être différent de zérola source
Pour la mise à jour des SQL:
la source
Il n'y a pas de réglage global magique «désactiver la division par 0 exception». L'opération doit renvoyer, car la signification mathématique de x / 0 est différente de la signification NULL, elle ne peut donc pas retourner NULL. Je suppose que vous prenez soin de l'évidence et que vos requêtes ont des conditions qui devraient éliminer les enregistrements avec le diviseur 0 et ne jamais évaluer la division. Le «piège» habituel est que la plupart des développeurs s'attendent à ce que SQL se comporte comme des langages procéduraux et offre un court-circuit à l'opérateur logique, mais ce n'est PAS le cas . Je vous recommande de lire cet article: http://www.sqlmag.com/Articles/ArticleID/9148/pg/2/2.html
la source
Voici une situation où vous pouvez diviser par zéro. La règle commerciale est que pour calculer les rotations des stocks, vous prenez le coût des marchandises vendues pour une période, l'annualisez. Une fois que vous avez le nombre annualisé, vous divisez par l'inventaire moyen pour la période.
Je cherche à calculer le nombre de tours d'inventaire qui se produisent dans une période de trois mois. J'ai calculé que le coût des marchandises a été vendu au cours de la période de trois mois de 1 000 $. Le taux de vente annuel est de 4 000 $ (1 000 $ / 3) * 12. L'inventaire de début est 0. L'inventaire de fin est 0. Mon inventaire moyen est maintenant 0. J'ai des ventes de 4000 $ par an et aucun inventaire. Cela donne un nombre infini de tours. Cela signifie que tout mon inventaire est converti et acheté par les clients.
Il s'agit d'une règle commerciale sur la façon de calculer les rotations des stocks.
la source
la source
Filtrez les données en utilisant une clause where afin de ne pas obtenir de valeurs 0.
la source
Parfois, 0 peut ne pas être approprié, mais parfois 1 n'est pas non plus approprié. Parfois, un saut de 0 à 100 000 000 décrit comme un changement de 1 ou 100% peut également être trompeur. 100 000 000 pour cent pourraient être appropriés dans ce scénario. Cela dépend du type de conclusions que vous avez l'intention de tirer en fonction des pourcentages ou des ratios.
Par exemple, un article à très petite vente passant de 2 à 4 vendus et un article à très grande vente passant de 1 000 000 à 2 000 000 vendus pourraient signifier des choses très différentes pour un analyste ou pour la direction, mais ils se présenteraient tous les deux à 100% ou 1. changement.
Il peut être plus facile d'isoler les valeurs NULL que de parcourir un groupe de lignes de 0% ou 100% mélangées à des données légitimes. Souvent, un 0 dans le dénominateur peut indiquer une erreur ou une valeur manquante, et vous ne voudrez peut-être pas simplement remplir une valeur arbitraire juste pour rendre votre ensemble de données bien rangé.
la source
Voici comment je l'ai corrigé:
IIF (ValueA! = 0, Total / ValueA, 0)
Il peut être encapsulé dans une mise à jour:
SET Pct = IIF (ValueA! = 0, Total / ValueA, 0)
Ou dans une sélection:
SELECT IIF (ValueA! = 0, Total / ValueA, 0) AS Pct FROM Tablename;
Pensées?
la source
Vous pouvez gérer l'erreur de manière appropriée lorsqu'elle se propage au programme appelant (ou l'ignorer si c'est ce que vous voulez). En C #, toutes les erreurs qui se produisent en SQL lèveront une exception que je pourrai intercepter puis gérer dans mon code, comme toute autre erreur.
Je suis d'accord avec Beska en ce que vous ne voulez pas cacher l'erreur. Vous n'avez peut-être pas affaire à un réacteur nucléaire, mais cacher des erreurs en général est une mauvaise pratique de programmation. C'est l'une des raisons pour lesquelles la plupart des langages de programmation modernes implémentent une gestion structurée des exceptions pour découpler la valeur de retour réelle avec un code d'erreur / d'état. Cela est particulièrement vrai lorsque vous faites des mathématiques. Le plus gros problème est que vous ne pouvez pas distinguer entre un 0 correctement calculé renvoyé ou un 0 à la suite d'une erreur. Au lieu de cela, toute valeur renvoyée est la valeur calculée et si quelque chose se passe mal, une exception est levée. Cela variera bien sûr en fonction de la façon dont vous accédez à la base de données et de la langue que vous utilisez, mais vous devriez toujours pouvoir recevoir un message d'erreur que vous pouvez traiter.
la source
Utilisez
NULLIF(exp,0)
mais de cette façon -NULLIF(ISNULL(exp,0),0)
NULLIF(exp,0)
casse si exp estnull
maisNULLIF(ISNULL(exp,0),0)
ne cassera pasla source