This post was originally published on this site
Manchmal geht man davon aus, dass die mitgelieferte Funktionen des SQL Servers das tun, was sie sollen. Aber dieses erwartete Verhalten trifft nicht immer zu. Wie im vorliegenden Fall der Funktion isNumeric.
Was habe ich erwartet: Ich habe erwartet, dass die Funktion isNumeric den übergebenen Parameter auswertet und als Resultat entweder 1 oder 0 zurückgibt, je nachdem ob es sich um einen numerischen Wert handelt, oder nicht.
Wie ist das Verhalten: Leider funktioniert die Funktion isNumeric nicht immer richtig – oder noch schlimmer, es werden Fehler geworfen (beim Datentyp date), wo man es absolut nicht erwartet.
Beispiele
T-SQL Code | Datentyp | Ergebnis | Bemerkung |
declare @myAttribute as decimal(18,6) = 123456789012.123456; select isnumeric (@myAttribute); | decimal | 1 | korrekt |
declare @myAttribute as date = ‚2016-02-17‘; select isnumeric (@myAttribute); | date | kein | Folgender Fehler wird geworden: Msg 8116, Level 16, State 1, Line 8 Argument data type date is invalid for argument 1 of isnumeric function. |
declare @myAttribute as datetime = CURRENT_TIMESTAMP; select isnumeric (@myAttribute); | datetime | 0 | korrekt – erstaunlich, dass datetime geht und date nicht … |
declare @myAttribute as varchar(12) = ‚Hallo‘; select isnumeric (@myAttribute); | varchar | 0 | korrekt |
declare @myAttribute as varchar(12) = ‚4711‘; select isnumeric (@myAttribute); | varchar | 1 | korrekt. D.h. mit isnumeric lassen sich auch varchar-Variablen untersuchen. |
declare @myAttribute as varchar(12) = ‚€4711‘; select isnumeric (@myAttribute); | varchar | 1 | korrekt. Trotzdem hätte ich hier evtl. eine 0 erwartet. In der Dokumentation von Microsoft kann man nachlesen, das die führende Zeichen wie +, – sowie Währungssymbole nicht ausgewertet werden. |
Nun könnte man ja auf die Idee kommen, zuerst mit der Funktion SQL_VARIANT_PROPERTY den Datentypen zu checken:
declare @myAttribute as date = '2016-02-17'
if SQL_VARIANT_PROPERTY(@myAttribute,'BaseType') not in ('decimal','numeric','float','real','int','bigint','smallint','tinyint','money','smallmoney') print 'not a numeric type' else select isnumeric(@myAttribute)
Doch auch hier wird der Ausruck ausgewertet und ein Fehler geworfen:
Msg 8116, Level 16, State 1, Line 6
Argument data type date is invalid for argument 1 of isnumeric function.
Als nächstes habe ich das gleiche mit einem CASE Statement versucht. Aber auch hier gibts eine Fehlermeldung:
declare @myAttribute as date = '2016-02-17'
SELECT CASE WHEN SQL_VARIANT_PROPERTY(@myAttribute,'BaseType') not in ('decimal','numeric','float','real','int','bigint','smallint','tinyint','money','smallmoney') THEN 0 ELSE isnumeric(@myAttribute) END AS isAttributeNumeric Msg 8116, Level 16, State 1, Line 3 Argument data type date is invalid for argument 1 of isnumeric function.
Fazit
Mein Fazit: Die Funktion isNumeric ist mit Vorsicht zu geniessen. Wenn sie eingesetzt wird, dann muss man sehr gut testen. Insbesondere muss sichergestellt werden, dass nie ein Parameter vom Datentyp date an die Funktion übergeben wird. Dann nämlich knallts und ein Fehler wird geworfen. Falls SQL Server 2012 oder höher eingesetzt wird, gibt es hier eine Empfehlung immer TryParse anstatt isNumeric einzusetzen.