Meine Artikelserie zum Thema “Advanced T-SQL” umfasste bislang diese Beiträge:
Im Rahmen meines nun folgenden Artikels wird auf Kurzschlussauswertungen in Verbindung mit T-SQL und dem Microsoft SQL-Server eingegangen. Dabei werden insbesondere auch einige mögliche Stolperfallen bei der Konvertierung numerischer Werte mit den SQL-Datentypen VARCHAR und NVARCHAR aufgezeigt.
Short-Circuit Evaluation in modernen Programmiersprachen
Durch das Konzept der Kurschlussauswertung kann oftmals einen Gewinn hinsichtlich der Performance erzielt werden. Insbesondere Compiler moderner objektorientierter Programmiersprachen wie C# oder Java verwenden daher Kurzschlussauswertungen als Mittel zur Optimierung. Anhand des folgendes C#-Snippets wird dies exemplarisch belegt:
1: private static bool ComplexCheckMethod()
2: {
3: // Some C#-Code
4: return [CheckResult];
5: }
6:
7: static void Main(string[] args)
8: {
9: if (false && ComplexCheckMethod())
10: {
11: ...
12: }
13: }
Da die Bedingung innerhalb der if-Anweisung (Zeile 9) niemals wahr werden bzw. den Wert “true” annehmen kann, wird das Ergebnis der zuvor implementierten ComplexCheckMethod-Funktion an dieser Stelle nicht benötigt und der Quellcode innerhalb der Funktion somit gar nicht erst ausgeführt. Moderne Entwickler-Tools wie beispielsweise der ReSahrper der Firma JetBranis erkennen dies und weisen den Entwickler darauf hin.
Short-Circuit Evaluation in T-SQL
Mit T-SQL innerhalb des SQL-Server verhält es sich bezüglich Kurzschlussauswertungen (leider) etwas anders. Hier hängt der Einsatz einer möglichen Short-Circuit Evaluation vom eingesetzten Datentypen innerhalb des T-SQL-Statements ab. Wird beispielsweise diese Tabellenstruktur
1: CREATE TABLE TblShortCircuitEvaluation
2: (
3: VarCharColumn VARCHAR(1000),
4: NVarCharColumn NVARCHAR(1000),
5: );
mit folgendem Inhalt verwendet
so liefert eine Abfrage mit Filter auf die VARCHAR(1000)-Spalte
SELECT *
FROM TblShortCircuitEvaluation
WHERE ISNUMERIC(VarCharColumn) = 1 AND (CAST(VarCharColumn AS INT) = 42);
ein gültiges Abfrageergebnis, nämlich:
Wird dagegen die gleiche Filterbedingung auf die NVARCHAR(1000)-Spalte angewendet, also folgendes Statement abgesetzt
SELECT *
FROM TblShortCircuitEvaluation
WHERE ISNUMERIC(NVarCharColumn) = 1 AND (CAST(NVarCharColumn AS INT) = 42);
, so wird statt eines Abfrageergebnisses ein Konvertierungsfehler zurückgegeben:
Msg 245, Level 16, State 1, Line 1
Conversion failed when converting the nvarchar value 'TextValue' to data type int.
In zweiten Fall, also bei Verwendung der NVARCHAR(1000)-Spalte, wird für alle Datensätze innerhalb der Datenbanktabelle, auch wenn die erste Bedingung ISNUMERIC(NVarCharColumn)=1 keinen TRUE-Wert zurückliefert, die anschließende Konvertierung versucht durchzuführen und die zweite Filterbedingung ausgewertet. Hierbei entsteht nun der oben aufgeführte der Konvertierungsfehler.
Warum dieses Verhalten genau so an den Tag gelegt wird, ist leider nicht klar ersichtlich. Im Internet existieren zwar zahlreiche Foren und Portale, die sich mit dem Thema Kurzschlussauswertung und SQL auseinander setzen, aber eine genaue Erklärung dafür kann nicht gefunden werden. Selbst dem standardisierten ANSI-SQL ist nur folgendes Zitat zu entlocken:
"Where the precedence is not determined by the Formats or by parentheses, effective evaluation of expressions is generally performed from left to right. However, it is implementation-dependent whether expressions are actually evaluated left to right, particularly when operands or operators might cause conditions to be raised or if the results of the expressions can be determined without completely evaluating all parts of the expression." (Kapitel 6.3.3.3 Rule evaluation order, Seite 41 ff)
Auf gut Deutsch: Im SQL wird die abgekürzte boolesche Evaluation leider nicht automatisch verwendet. Die Datenbank-Implementation kann sie gebrauchen, muss aber nicht .
Damit die obere Abfrage mit Filter auf der NVARCHAR(1000)-Spalte auch fehlerfrei ausgewertet und ein gültiges Ergebnis zurückliefert, empfiehlt es sich eine kleine Sicherheit im SQL-Statement einzubauen. Diese könnte beispielsweise wie folgt aussehen:
SELECT *
FROM TblShortCircuitEvaluation
WHERE CAST((CASE WHEN ISNUMERIC(NVarCharColumn) = 1 THEN NVarCharColumn END) AS INT) = 42;
Hier wird nun ein gültiges Abfrageergebnis zurückgeliefert, nämlich:
Fazit
Im diesem Artikel wurde gezeigt, dass leider weder mit T-SQL innerhalb des Microsoft SQL-Server noch mit standardisierten ANSI-SQL abgekürzte boolesche Evaluationen mittels Kurschlussauswertung wirklich garantiert werden können. Um auf Nummer sicher zu gehen, empfiehlt es sich sogar immer von einer Prüfung und Auswertung alle Terme bzw. sämtliche einzelne Bedingungen eines SQL-Statements auszugehen.
Des Weiteren sollten auch in Anbetracht von Kurzschlussauswertung Änderungen von SQL-Datentypen immer kritisch hinterfragt werden. Selbst anfangs unbedenklich erscheinende Aussagen wie "Wir ändern mal eben schnell den Datentyp von VARCHAR auf NVARCHAR" können durchaus gefährlich sein und unerwünschte Auswirkungen auf bestehende SQL-Statements haben. Die Code-Beispiele in diesem Artikel zeigen dies deutlich und es gilt auch hier das bekannte Sprichwort: der Teufel steckt im Detail .
Quellen:
-
char und varchar (Transact-SQL) (Letzter Zugriff: 2014-12-12)
-
nchar und nvarchar (Transact-SQL) (Letzter Zugriff: 2014-12-12)
-
ISO/IEC FDIS 9075 Information technology Part 1: Database languages – SQL – Framework (SQL/Framework) (Letzter Zugriff: 2014-12-12)
Sie sehen gerade einen Platzhalterinhalt von Facebook. Um auf den eigentlichen Inhalt zuzugreifen, klicken Sie auf die Schaltfläche unten. Bitte beachten Sie, dass dabei Daten an Drittanbieter weitergegeben werden.
Mehr InformationenSie sehen gerade einen Platzhalterinhalt von Instagram. Um auf den eigentlichen Inhalt zuzugreifen, klicken Sie auf die Schaltfläche unten. Bitte beachten Sie, dass dabei Daten an Drittanbieter weitergegeben werden.
Mehr InformationenSie sehen gerade einen Platzhalterinhalt von X. Um auf den eigentlichen Inhalt zuzugreifen, klicken Sie auf die Schaltfläche unten. Bitte beachten Sie, dass dabei Daten an Drittanbieter weitergegeben werden.
Mehr Informationen