Her er fem muligheder for at håndtere fejlmeddelelse 8134 "Del med nul fejl opstået" i SQL Server.
Fejlen
For det første er her et eksempel på kode, der producerer den fejl, vi taler om:
SELECT 1 / 0;
Resultat:
Msg 8134, Level 16, State 1, Line 1 Divide by zero error encountered.
Vi får fejlen, fordi vi forsøger at dividere et tal med nul. Matematisk giver dette ingen mening. Du kan ikke dividere et tal med nul og forvente et meningsfuldt resultat.
For at håndtere denne fejl skal vi beslutte, hvad der skal returneres, når vi forsøger at dividere med nul. For eksempel vil vi måske have en nulværdi, der returneres. Eller vi vil måske have nul tilbage. Eller en anden værdi.
Nedenfor er nogle muligheder for at håndtere denne fejl.
Mulighed 1:NULLIF()
Udtryk
En hurtig og nem måde at håndtere denne fejl på er at bruge NULLIF()
udtryk:
SELECT 1 / NULLIF( 0, 0 );
Resultat:
NULL
NULLIF()
returnerer NULL
hvis de to angivne udtryk har samme værdi. Det returnerer det første udtryk, hvis de to udtryk er forskellige. Derfor, hvis vi bruger nul som det andet udtryk, vil vi få en nulværdi, når det første udtryk er nul. At dividere et tal med NULL
resulterer i NULL
.
Faktisk returnerer SQL Server allerede NULL
på en divider-med-nul fejl, men i de fleste tilfælde kan vi ikke se dette på grund af vores ARITHABORT
og ANSI_WARNINGS
indstillinger (mere om dette senere).
Mulighed 2:Tilføj ISNULL()
Funktion
I nogle tilfælde foretrækker du måske at returnere en anden værdi end NULL
.
I sådanne tilfælde kan du videregive det forrige eksempel til ISNULL()
funktion:
SELECT ISNULL(1 / NULLIF( 0, 0 ), 0);
Resultat:
0
Her specificerede jeg, at nul skulle returneres, når resultatet er NULL
.
Vær dog forsigtig. I nogle tilfælde kan det være upassende at returnere nul. Hvis du f.eks. beskæftiger dig med lagerbeholdninger, kan angivelse af nul betyde, at der er nul produkter, hvilket måske ikke er tilfældet.
Mulighed 3:Brug en CASE
Erklæring
En anden måde at gøre det på er at bruge en CASE
erklæring:
DECLARE @n1 INT = 20;
DECLARE @n2 INT = 0;
SELECT CASE
WHEN @n2 = 0
THEN NULL
ELSE @n1 / @n2
END
Resultat:
NULL
Mulighed 4:SET ARITHABORT
Erklæring
SET ARITHABORT
sætning afslutter en forespørgsel, når der opstår en overløbs- eller divider-med-nul fejl under udførelse af forespørgsel. Vi kan bruge det sammen med SET ANSI WARNINGS
for at returnere NULL
når divider-med-nul-fejlen kan forekomme:
SET ARITHABORT OFF;
SET ANSI_WARNINGS OFF;
SELECT 20 / 0;
Resultat:
NULL
Microsoft anbefaler, at du altid indstiller ARITHABORT
til ON
i dine logon-sessioner, og at sætte den til OFF
kan have en negativ indvirkning på forespørgselsoptimering, hvilket fører til ydeevneproblemer.
Nogle klienter (såsom SQL Server Management Studio) sæt ARITHABORT
til ON
som standard. Det er derfor, du sandsynligvis ikke kan se NULL
værdi, der returneres, når du dividerer med nul. Du kan bruge SET ARITHIGNORE
for at ændre denne adfærd, hvis du foretrækker det.
Mulighed 5:SET ARITHIGNORE
Erklæring
SET ARITHIGNORE
sætning styrer, om fejlmeddelelser returneres fra overløb eller divider-med-nul fejl under en forespørgsel:
SET ARITHABORT OFF;
SET ANSI_WARNINGS OFF;
SET ARITHIGNORE ON;
SELECT 1 / 0 AS Result_1;
SET ARITHIGNORE OFF;
SELECT 1 / 0 AS Result_2;
Resultat:
Commands completed successfully. Commands completed successfully. Commands completed successfully. +------------+ | Result_1 | |------------| | NULL | +------------+ (1 row affected) Commands completed successfully. +------------+ | Result_2 | |------------| | NULL | +------------+ Division by zero occurred.
Her indstiller jeg ARITHABORT
og ANSI_WARNINGS
til OFF
så sætningen ikke blev afbrudt på grund af fejlen, og NULL
returneres, når der er en divider-med-nul fejl.
Bemærk, at SET ARITHIGNORE
indstilling styrer kun, om en fejlmeddelelse returneres. SQL Server returnerer en NULL
i en beregning, der involverer et overløb eller divider-med-nul fejl, uanset denne indstilling.
I ovenstående eksempel kan vi se, at når ARITHIGNORE
er ON
, divisionen med nul-fejlen returneres ikke. Når den er OFF
, divideres med nul fejlmeddelelsen returneres.