Ich bin kürzlich auf ein interessantes Problem gestoßen, bei dem CASE
-Anweisungen in ISNULL
-Funktionen in TSQL geändert wurden. Die Abfrage, mit der ich gearbeitet habe, wird verwendet, um einige Benutzerattribute und Berechtigungen für eine Website zu erhalten, an der ich arbeite. Zuvor hatte die Abfrage eine Anzahl von CASE
-Anweisungen ähnlich der folgenden:
HINWEIS: a.column1
im Beispiel hat den Typ bit
in der Tabelle. Beachten Sie auch, dass die Spalte [CanDoSomething]
result manchmal als Zeichenfolge in der Website verwendet wird.
Der DBA hat diese CASE
-Anweisungen durch die ISNULL
-Funktion ersetzt:
Dies scheint eine feine Änderung zu sein, aber es verursachte etwas Unerwartetes beim Abrufen der Daten in C #. Bei der vorherigen Abfrage war der Wert der Spalte [CanDoSomething]
beim Zugriff von DataTable
in C # 1
oder 0
. Als wir zu ISNULL
wechselten, wurde der Wert in C # in true
oder false
geändert, was, wenn er als String behandelt wird, offensichtlich nicht mit 1
oder 0
identisch ist.
Die Fehler, die dadurch verursacht wurden, wurden bereits behoben. Ich bin nur neugierig, warum ISNULL
einen anderen Wert zurückgibt als eine entsprechende CASE
-Anweisung und ich kann keine Antworten auf Google finden.
Um die Erklärung von @ dasblinkenlight zu erweitern:
Das eigentliche Problem ist, dass pro die Dokumentation , case
expressions
gibt den höchsten Prioritätstyp aus der Menge der Typen zurück * result_expressions * und der optionale * else_result_expression *. Weitere Informationen finden Sie unter Datentyppräzedenz (Transact-SQL) .
Während isnull()
gibt den gleichen Typ wie * check_expression *
zurück
In Ihrem Fall ist das ein bit
. Ihr case
Ausdruck:
verfügt über Ausführungspfade, die zwei verschiedene Datentypen zurückgeben, ein int
(der Literalwert 0
) und ein bit
(der Wert der Spalte). Wenn Sie sich das Datentyp-Präzedenzdiagramm ansehen, das oben verlinkt ist, hat int
einen höheren Vorrang als bit
und somit der Wert bit
wird in int
umgewandelt.
Das liegt daran, dass die Konvertierung von bit
nach int
eine Erweiterung ist. Der bit
-Typ von Sql Server ist im Wesentlichen ein 1-Bit-Integer-Wert und daher sind keine Daten verloren. Die Konvertierung von int
nach bit
ist eine einschränkende Konvertierung und die Möglichkeit eines Datenverlusts besteht (zumindest im Konzept).
Sie hätten dieses Problem nicht kennen, wenn der Datenbankadministrator coalesce()
verwendet hätte anstelle von isnull()
, was meine persönliche Entscheidung gewesen wäre, da coalesce()
so definiert ist, dass es einen ähnlichen Typ wie case
zurückgibt. coalesce()
Gibt den Datentyp von Ausdruck mit der höchsten Datentyppriorität zurück. Wenn alle Ausdrücke nicht nullbar sind, wird das Ergebnis als nichtnullable eingegeben.
Die Antwort darauf finden Sie in der Dokumentation des Rückgabetyps ISNULL
:
ISNULL ( check_expression , replacement_value )
Gibt den gleichen Typ wie
check_expression
zurück. Wenn ein LiteralNULL
alscheck_expression
bereitgestellt wird, wird der Datentyp des Ersetzungswerts zurückgegeben. Wenn ein LiteralNULL
alscheck_expression
bereitgestellt wird und keinreplacement_value
bereitgestellt wird, wird einint
zurückgegeben.
Im Gegensatz zu Ihrem CASE
-Ausdruck, der immer zurückgibt, gibt * einen int
int
zurück, da in der ersten Verzweigung eine Null steht, ISNULL
gibt a zurück Wert des Typs seines ersten Parameters, dh a.column1
.
* Der Ausdruck
CASE
war vor der Bearbeitung WHEN a.column1 IS NULL THEN 0 ELSE 1
.