2016-07-06 3 views
5

Ich habe die folgende Abfrage:Hat CASE-Ausdruck alle Fälle vor der Verarbeitung ausgewertet?

SELECT 
CASE 
    WHEN 'Sara' like '% %' THEN SUBSTRING('Sara', 1, CHARINDEX(' ', 'Sara') - 1) 
    ELSE 'Sara' 
END AS FirstName, 
CASE 
    WHEN 'Sara' like '% %' THEN SUBSTRING('Sara', CHARINDEX(' ', 'Sara') + 1, 8000) 
    ELSE '' 
END AS LastName 

ziemlich geradlinig - Ich teste einen Namen Split-Abfrage. Also ich das Szenario testen, wo der Name keine Leerzeichen hat und ich die folgende Ausnahme bekomme:

Ungültige Länge Parameter an die SUBSTRING Funktion übergeben.

Warum ist das? Sollte es nicht die erste Klausel auswerten und sofort auf die ELSE gehen? Wie komme ich da um ..?

+0

1) Fallausdruck, nicht Fallaussage. 2) Wahrscheinlich ist die Antwort NEIN. Zumindest nicht logisch. (Die Implementierung ist produktspezifisch.) – jarlh

+2

Sie wissen, dass Sie die Zeichenfolge "Sara" und nicht ein Feld vergleichen, richtig? – Siyual

+0

Warum würde es dann eine Ausnahme mit Teilzeichenfolge werfen? Ich bin etwas verwirrt. – user2124871

Antwort

11

Der Optimierer ist intelligent genug, um zu bemerken, dass Sie einen konstanten Ausdruck haben und versuchen, ihn auszuwerten. die Konstante durch eine variable Übergeben, um sie auszuführen Trick würde: THEN Ausdruck

DECLARE @TestString nvarchar(100) = 'Sara'; 

SELECT 
    CASE 
     WHEN @TestString like '% %' 
     THEN SUBSTRING(@TestString, 1, CHARINDEX(' ', @TestString) - 1) 
     ELSE @TestString 
    END AS FirstName, 
    CASE 
     WHEN @TestString like '% %' 
     THEN SUBSTRING(@TestString, CHARINDEX(' ', @TestString) + 1, 8000) 
     ELSE '' 
    END AS LastName 

die Frage zu beantworten, würde Prozessor nur berechnen, wenn WHEN ist wahr, sonst wird es nur ELSE Ausdruck berechnen. Aber schon vorher würde Optimizer versuchen, alle konstanten Ausdrücke durch berechnete Werte zu ersetzen, so dass der Prozessor sie nicht für jede Zeile neu berechnen muss. Es heißt "Constant Folding".

+0

Ah.Wenn der Optimierer also einen statischen/konstanten Wert sieht, wird festgestellt, dass der Vergleichsausdruck "Gefällt mir" bereits ausgewertet wurde. – user2124871

+2

Es wird versucht, den Ausdruck durch einen berechneten Wert zu ersetzen, damit der Prozessor ihn nicht für jede Zeile neu berechnen muss. –

+0

Gotcha. Danke für die Information - schätzen Sie es. – user2124871

7

Verwendung einer Variablen funktioniert;

DECLARE @NameString varchar(10); SET @NameString = 'Sara' 

SELECT 
CASE 
    WHEN @NameString like '% %' THEN SUBSTRING(@NameString, 1, CHARINDEX(' ', @NameString) - 1) 
    ELSE @NameString 
END AS FirstName, 
CASE 
    WHEN @NameString like '% %' THEN SUBSTRING(@NameString, CHARINDEX(' ', @NameString) + 1, 8000) 
    ELSE '' 
END AS LastName 

Das Problem mit Ihrem Code ist, dass es überprüft, dass jedes Teil funktioniert, wenn ein statischer Wert übergeben wird. Es mag nicht, dass CHARINDEX(' ', 'Sara') - 1 zu -1 aufgelöst wird. Ein Hack, um dies zu umgehen, wäre es, diese Funktion in die ABS() Funktion einzubinden;

SELECT 
CASE 
    WHEN 'Sara' like '% %' THEN SUBSTRING('Sara', 1, ABS(CHARINDEX(' ', 'Sara') - 1)) 
    ELSE 'Sara' 
END AS FirstName, 
CASE 
    WHEN 'Sara' like '% %' THEN SUBSTRING('Sara', CHARINDEX(' ', 'Sara') + 1, 8000) 
    ELSE '' 
END AS LastName 
+0

Sehr gut erklärt - zwischen den beiden Antworten verstehe ich, was jetzt passiert. Danke für die Information. – user2124871