Comment éviter l'erreur «diviser par zéro» dans SQL?

363

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 NULLIFclause?

Y a-t-il une meilleure façon, ou comment cela peut-il être appliqué?

Henrik Staun Poulsen
la source
7
Une validation des données est peut-être nécessaire.
Anthony

Réponses:

645

Afin d'éviter une erreur de "Division par zéro" nous l'avons programmée comme ceci:

Select Case when divisor=0 then null
Else dividend / divisor
End ,,,

Mais voici une manière beaucoup plus agréable de le faire:

Select dividend / NULLIF(divisor, 0) ...

Maintenant, le seul problème est de se souvenir du bit NullIf, si j'utilise la touche "/".

Henrik Staun Poulsen
la source
13
Une manière beaucoup plus agréable de le faire "Sélectionnez dividende / nullif (diviseur, 0) ..." casse si le diviseur est NULL.
Anderson
8
@Anderson Ce n'est pas vrai du tout. Êtes-vous sûr de ne pas avoir utilisé accidentellement IsNullau lieu de NullIf? 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 avec IsNullou Coalesce.
ErikE
1
@ErikE, c'est vrai ... essayez d'exécuter ... sélectionnez 1 / nullif (null, 0) ... vous obtenez "Le type du premier argument de NULLIF ne peut pas être la constante NULL car le type du premier argument a être connu." Gérez cela en utilisant "coalesce (FieldName, 0)" ... par exemple sélectionnez 1 / nullif (coalesce (null, 0), 0)
John Joseph
1
@JohnJoseph Je ne peux pas dire si vous êtes d'accord avec moi ou si vous vous disputez avec moi.
ErikE
2
@JohnJoseph Regardez de plus près l'erreur que vous avez obtenue. Oui, SELECT 1 / NULLIF(NULL, 0)échoue, mais c'est parce qu'il a NULLIF()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 table NULLIF()plutôt qu'une NULLconstante. 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.
MarredCheese
180

Dans le cas où vous souhaitez retourner zéro, dans le cas où une déviation zéro se produirait, vous pouvez utiliser:

SELECT COALESCE(dividend / NULLIF(divisor,0), 0) FROM sometable

Pour chaque diviseur qui est nul, vous obtiendrez un zéro dans le jeu de résultats.

Tobias Domhan
la source
9
Certains benchmarks révèlent que COALESCE est légèrement plus lent qu'ISNULL. Cependant, COALESCE est dans les normes et est donc plus portable.
Paul Chernoch
37
Si quelqu'un d'autre ne comprend pas instantanément pourquoi cela fonctionne, NULLIF (d, 0) renverra NULL si d vaut 0. En SQL, la division par NULL renvoie NULL. Le Coalesce remplace le NULL résultant par 0.
GuiSim
16
@SQLGeorge Bien que je sois d'accord avec votre argument, veuillez noter qu'il y a des cas où l'on se soucie plus de ce qui est statistiquement correct que mathématiquement correct. Dans certains cas, lorsque vous utilisez des fonctions statistiques, 0 ou même 1 est un résultat acceptable lorsque le diviseur est nul.
Athafoud
10
Quelqu'un peut-il m'expliquer pourquoi c'est mauvais? Si j'essaie de trouver un pourcentage et que le diviseur est nul, je veux très certainement que le résultat soit zéro pour cent.
Todd Sharp
10
Je pense que @George et @ James / Wilson ont fondamentalement mal compris la question posée. Il existe certainement des applications commerciales où le retour d'un "0" est approprié, même si ce n'est pas techniquement vrai d'un point de vue mathématique.
Sean Branchaw
66

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 :

SELECT club_id, males, females, males/females AS ratio
  FROM school_clubs;

Vous pouvez utiliser la fonction NULLIFpour éviter la division par zéro. NULLIFcompare deux expressions et renvoie null si elles sont égales ou la première expression sinon.

Réécrivez la requête comme suit:

SELECT club_id, males, females, males/NULLIF(females, 0) AS ratio
  FROM school_clubs;

Tout nombre divisé par NULLdonne NULLet aucune erreur n'est générée.

franc
la source
6
Oui en effet, c'est bien mieux que cette autre réponse qui a eu tant de votes positifs. Dans votre solution, vous avez au moins un NULL, ce qui indique que vous ne pouvez pas fournir un résultat correct. Mais si vous convertissez le résultat de NULL en zéro, vous obtenez simplement des résultats erronés et trompeurs.
SQL Police
8
Soit dit en passant, si vous voulez calculer un ratio mâle / femelle, alors je suggère de mieux comparer au total, comme ceci: 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.
SQL Police
44

Vous pouvez également le faire au début de la requête:

SET ARITHABORT OFF 
SET ANSI_WARNINGS OFF

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.

Taz
la source
1
Travaille pour moi. Dans mon cas, je dois utiliser l'opération de division à la clause WHERE. Je suis sûr qu'il n'y a pas de diviseur zéro, car lorsque je commente O WH dehors, il n'y a pas de valeurs nulles aux résultats. Mais en quelque sorte, l'optimiseur de requêtes divise par zéro lors du filtrage. SET ARITHABORT OFF SET et ANSI_WARNINGS OFF ça marche - après 2 jours de combat avec division par zéro à la clause WHERE. THX!
huhu78
2
Ce "se sent" tellement sale mais je l'aime! J'en avais besoin dans une requête qui fait une agrégation et utilise une instruction CASE n'était pas une option car alors j'ai dû ajouter cette colonne au GROUP BY qui a totalement changé les résultats. Faire de la requête initiale une sous-sélection puis effectuer un GROUP BY sur la requête externe modifie également les résultats car il y a une division impliquée.
Andrew Steitz
1
OK, donc j'aime toujours cette "solution" mais comme beaucoup d'entre vous l'ont probablement ressenti, je pensais qu'il devait y avoir une méthode "plus propre". Que faire si j'ai oublié de réactiver les avertissements? Ou quelqu'un a cloué mon code (ça n'arrive jamais, non?) Et n'a pas pensé aux avertissements? Quoi qu'il en soit, j'ai vu d'autres réponses sur NULLIF (). Je connaissais NULLIF () mais je n'ai pas réalisé que la division par NULL renvoie NULL (je pensais que ce serait une erreur). Alors ... je suis allé avec ce qui suit: ISNULL ((SUM (foo) / NULLIF (SUM (bar), 0)), 0) AS Avg
Andrew Steitz
2
Je ne connaissais pas cette solution. Je ne suis pas sûr de l'aimer, mais il pourrait être utile de le savoir un jour. Merci beaucoup.
Henrik Staun Poulsen
1
Il s'agit de la solution la plus simple, mais notez que cela nuira aux performances. D'après docs.microsoft.com/en-us/sql/t-sql/statements/… : "La définition de ARITHABORT sur OFF peut avoir un impact négatif sur l'optimisation des requêtes, entraînant des problèmes de performances."
mono blaine
36

Vous pouvez au moins empêcher la requête de se rompre avec une erreur et retourner NULLs'il y a une division par zéro:

SELECT a / NULLIF(b, 0) FROM t 

Cependant, je ne convertirais JAMAIS cela en zéro avec coalescecomme 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.

Police SQL
la source
32

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.

Beska
la source
15
Je ne suis pas d'accord. Vos règles commerciales ne devraient jamais finir par faire des calculs illégaux. Si vous finissez par faire quelque chose comme ça, votre modèle de données est probablement incorrect. Chaque fois que vous rencontrez une division par 0, vous devriez vous demander si les données auraient dû être NULL au lieu de 0.
Remus Rusanu
32
Je ne peux pas croire que j'ai été dévalorisé par quelqu'un qui me demande si j'ai déjà "fait une vraie programmation?" parce que je dis de bien faire plutôt que d'être paresseux. soupir
Beska
11
Je suis désolé, je ne voulais pas vous offenser. Mais la question est parfaitement valable dans de nombreuses applications LOB courantes, et y répondre par une "division par 0 n'est pas légal" n'ajoute pas de valeur à mon humble avis.
Eduardo Molteni
2
@JackDouglas Droite. C'est un cas où vous voulez que les règles métier gèrent un cas spécial d'une manière spéciale ... mais ce ne devrait pas être le calcul sous-jacent qui renvoie un blanc. Ce devrait être la règle commerciale. La réponse acceptée renvoie un null, ce qui est une bonne façon de le gérer. Lancer une exception serait bien aussi. Le repérer et le manipuler avant qu'il ne passe au SQL serait sans doute l'idéal. Fournir une sorte de fonction que d'autres choses pourraient appeler et qui a renvoyé une valeur mathématiquement incorrecte n'est pas la voie à suivre, car ce cas spécial peut ne pas s'appliquer à ces autres appelants.
Beska
4
@JackDouglas Oui, c'est un bon résumé avec lequel je suis d'accord. À l'origine, la question semblait être formulée comme «que puis-je faire pour simplement cacher cette erreur». Depuis lors, il a évolué. Renvoyer une valeur nulle, la réponse à laquelle il arrive finalement, semble être une réponse raisonnable. (Je préconisais fortement de ne pas retourner un 0, ou un autre nombre.)
Beska
28
SELECT Dividend / ISNULL(NULLIF(Divisor,0), 1) AS Result from table

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.

Nisarg
la source
3
En raison de sa longueur, il a été recommandé de supprimer votre réponse. Notez qu'il est toujours préférable d'ajouter une petite explication de tout ce que vous proposez - même si cela semble très simple;)
Trinimon
10

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

 ISNULL(Numerator/NULLIF(Divisor,0),1)

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

NewScore = OldScore *  ISNULL(NewSampleScore/NULLIF(OldSampleScore,0),1) 

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é.

N Mason
la source
1
@N Mason; oui, parfois 1 est une option. Mais comment vous souvenez-vous de la partie ISNULL, lorsque vous tapez la barre oblique inverse?
Henrik Staun Poulsen le
1
Désolé Henrik - je ne suis pas sûr de comprendre la question.
N Mason
6

J'ai écrit une fonction il y a quelque temps pour la gérer pour mes procédures stockées :

print 'Creating safeDivide Stored Proc ...'
go

if exists (select * from dbo.sysobjects where  name = 'safeDivide') drop function safeDivide;
go

create function dbo.safeDivide( @Numerator decimal(38,19), @divisor decimal(39,19))
   returns decimal(38,19)
begin
 -- **************************************************************************
 --  Procedure: safeDivide()
 --     Author: Ron Savage, Central, ex: 1282
 --       Date: 06/22/2004
 --
 --  Description:
 --  This function divides the first argument by the second argument after
 --  checking for NULL or 0 divisors to avoid "divide by zero" errors.
 -- Change History:
 --
 -- Date        Init. Description
 -- 05/14/2009  RS    Updated to handle really freaking big numbers, just in
 --                   case. :-)
 -- 05/14/2009  RS    Updated to handle negative divisors.
 -- **************************************************************************
   declare @p_product    decimal(38,19);

   select @p_product = null;

   if ( @divisor is not null and @divisor <> 0 and @Numerator is not null )
      select @p_product = @Numerator / @divisor;

   return(@p_product)
end
go
Ron Savage
la source
2
Salut Ron, belle solution, sauf qu'elle a un type de données limité (4 décimales) et nos @diviseurs peuvent également être négatifs. Et comment appliquez-vous son utilisation? TIA Henrik Staun Poulsen
Henrik Staun Poulsen
1
Je l'ai lancé assez rapidement pour gérer un scénario de problème spécifique à l'époque. Application de développeur unique, donc l'application n'est pas si difficile, sauf pour ma mémoire. :-)
Ron Savage
5
Malgré l'instruction print, ce n'est pas un proc stocké, c'est un UDF scalaire. Cela vous tuera dans MS-SQL si cela fait partie d'une requête.
Mark Sowul
4
Je suis d'accord avec l'affirmation de Mark Sowul selon laquelle la fonction scalaire causera de la douleur. C'est une terrible suggestion dans T-SQL, ne le faites pas! Les fonctions scalaires sont des destructeurs de performances! Les fonctions de valeur de table en ligne sont les seules bonnes fonctions utilisateur dans SQL Server (éventuellement à l'exception des fonctions CLR qui peuvent bien fonctionner).
Davos
4
  1. Ajouter une contrainte CHECK qui force Divisorà être différent de zéro
  2. Ajoutez un validateur au formulaire afin que l'utilisateur ne puisse pas saisir de valeurs nulles dans ce champ.
finnw
la source
1
Je commence à aimer de plus en plus les contraintes CHECK.
Henrik Staun Poulsen
4

Pour la mise à jour des SQL:

update Table1 set Col1 = Col2 / ISNULL(NULLIF(Col3,0),1)
Vijay Bansal
la source
3
salut Vijay, Oui, cela fonctionnera, mais ... Je ferais attention à la partie ISNULL, où vous finissez par diviser par NULL. Je préfère signaler à l'utilisateur que le résultat est inconnu car le diviseur est nul.
Henrik Staun Poulsen
2
Cela m'a sauvé dans une sous-requête compliquée, merci.
QMaster
3

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

Remus Rusanu
la source
4
Il existe un tel "réglage global magique": ARRÊTEZ L'ARITHABORT.
David Manheim
3

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.

Jimmy
la source
3
Oui, vous avez alors un nombre infini de tours. Donc dans ce cas, si vous avez une division par zéro, alors vous devriez montrer quelque chose comme '#INF'.
SQL Police
1
"L'inventaire de début est 0. L'inventaire de fin est 0. Mon inventaire moyen est maintenant 0." Votre calcul est une estimation. À un certain moment, l'inventaire est positif ou vous ne pouvez rien expédier / vendre. Par conséquent, si vous n'êtes pas satisfait de + ∞, utilisez une meilleure estimation de l'inventaire moyen.
Tom Blodget
2
CREATE FUNCTION dbo.Divide(@Numerator Real, @Denominator Real)
RETURNS Real AS
/*
Purpose:      Handle Division by Zero errors
Description:  User Defined Scalar Function
Parameter(s): @Numerator and @Denominator

Test it:

SELECT 'Numerator = 0' Division, dbo.fn_CORP_Divide(0,16) Results
UNION ALL
SELECT 'Denominator = 0', dbo.fn_CORP_Divide(16,0)
UNION ALL
SELECT 'Numerator is NULL', dbo.fn_CORP_Divide(NULL,16)
UNION ALL
SELECT 'Denominator is NULL', dbo.fn_CORP_Divide(16,NULL)
UNION ALL
SELECT 'Numerator & Denominator is NULL', dbo.fn_CORP_Divide(NULL,NULL)
UNION ALL
SELECT 'Numerator & Denominator = 0', dbo.fn_CORP_Divide(0,0)
UNION ALL
SELECT '16 / 4', dbo.fn_CORP_Divide(16,4)
UNION ALL
SELECT '16 / 3', dbo.fn_CORP_Divide(16,3)

*/
BEGIN
    RETURN
        CASE WHEN @Denominator = 0 THEN
            NULL
        ELSE
            @Numerator / @Denominator
        END
END
GO
Gregory Hart
la source
Je n'aime pas votre solution, car l'utilisation d'un FDU oblige la requête à s'exécuter en mode thread unique. J'aime votre configuration de test. J'aimerais avoir cela dans tous nos FDU.
Henrik Staun Poulsen
Pour moi, cette solution est parfaite et élégante
Payedimaunt
@Payedimaunt; oui, les FDU conduisent à un code très élégant. Mais cela ne fonctionne pas bien. Il s'agit de "curseurs sur les somnifères". :-) Il est également difficile de se rappeler d'écrire dbo.Divide au lieu d'un "/" ordinaire
Henrik Staun Poulsen
1

Filtrez les données en utilisant une clause where afin de ne pas obtenir de valeurs 0.

nunespascal
la source
1

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é.

CASE
     WHEN [Denominator] = 0
     THEN NULL --or any value or sub case
     ELSE [Numerator]/[Denominator]
END as DivisionProblem
Joeyslaptop
la source
1
Je trouve que le problème est de se rappeler de faire quelque chose quand on veut faire une division. Si vous ne vous souvenez pas d'avoir ajouté CASE ou NULLIF, vous obtenez un dossier d'assistance dans x semaines, un lundi matin. Je déteste ça.
Henrik Staun Poulsen
1

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?

CorvetteGuru
la source
Moi et d'autres trouvons que remplacer "inconnu" par zéro est une solution dangereuse. Je préfère de loin NULL. Mais le plus difficile est de ne pas oublier d'ajouter iif ou nullif sur toutes les divisions!
Henrik Staun Poulsen
0

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.

try
{
    Database.ComputePercentage();
}
catch (SqlException e)
{
    // now you can handle the exception or at least log that the exception was thrown if you choose not to handle it
    // Exception Details: System.Data.SqlClient.SqlException: Divide by zero error encountered.
}
Despertar
la source
1
Je pense que nous sommes tous d'accord pour dire que cacher l'erreur avec un 0 n'est pas une solution. Ce que je propose est d'écrire notre code de telle sorte que chaque "/" soit suivi d'un "NULLIF". De cette façon, mon rapport / réacteur nucléaire n'est pas laissé seul, mais affiche un "NULL" au lieu de cette erreur embêtante Msg 8134. De cause, si j'ai besoin d'un processus différent lorsque le diviseur est 0, alors Beska et moi sommes d'accord. Nous devons coder cela. C'est juste difficile à faire à chaque fois que vous écrivez un "/". "/ NULLIF" n'est pas impossible à faire à chaque fois.
Henrik Staun Poulsen
0

Utilisez NULLIF(exp,0)mais de cette façon -NULLIF(ISNULL(exp,0),0)

NULLIF(exp,0)casse si exp est nullmais NULLIF(ISNULL(exp,0),0)ne cassera pas

Johnny Kancharla
la source
1
Je ne peux pas obtenir NULLIF (exp, 0), si 0 est un zéro, pas un o. Essayer; DECLARE @i INT SELECT 1 / NULLIF (@i, 0) pour voir si vous pouvez le faire casser.
Henrik Staun Poulsen