ISNULL vs CASE Rückgabetyp

8

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.

%Vor%

Der DBA hat diese CASE -Anweisungen durch die ISNULL -Funktion ersetzt:

%Vor%

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.

    
jvdub 06.12.2013, 17:53
quelle

2 Antworten

5

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:

%Vor%

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.

    
Nicholas Carey 06.12.2013, 18:55
quelle
5

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 Literal NULL als check_expression bereitgestellt wird, wird der Datentyp des Ersetzungswerts zurückgegeben. Wenn ein Literal NULL als check_expression bereitgestellt wird und kein replacement_value bereitgestellt wird, wird ein int zurückgegeben.

Im Gegensatz zu Ihrem CASE -Ausdruck, der immer zurückgibt, gibt int * einen 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 .     
dasblinkenlight 06.12.2013 18:01
quelle

Tags und Links