2016-07-06 101 views
5

Ho la seguente query:L'espressione CASE valuta tutti i casi prima dell'elaborazione?

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 

piuttosto straight-forward - sto testando una query di nome scissione. Così provo lo scenario in cui il nome non ha spazi e ottengo la seguente eccezione:

Parametro di lunghezza non valido passato alla funzione SUBSTRING.

Perché è quello? Dovrebbe non valutare la prima clausola e andare immediatamente allo ELSE? Come faccio a girare questo ..?

+0

1) Espressione caso, non caso. 2) Probabilmente la risposta è NO. Almeno non logicamente. (L'implementazione è specifica del prodotto.) – jarlh

+2

Ti rendi conto che stai confrontando la stringa letterale ''Sara'' e non un campo, giusto? – Siyual

+0

Quindi perché genera un'eccezione con la sottostringa? Sono un po 'confuso .. – user2124871

risposta

11

L'ottimizzatore è abbastanza intelligente da rilevare che è presente un'espressione costante e provare a valutarlo. Passando il costante attraverso una variabile sarebbe ingannare l'esecuzione:

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 

Per rispondere alla domanda, processore sarebbe calcolare THEN espressione solo se WHEN è vero, altrimenti si calcolerà solo ELSE espressione. Ma prima ancora che Optimizer provasse a sostituire tutte le espressioni costanti con i valori calcolati in modo che Processor non debba ricalcolarli per ogni riga. Si chiama "Constant Folding".

+0

Ah.Quindi, quando l'ottimizzatore vede un valore statico/costante, determina che l'espressione comparativa 'like' è già stata valutata? – user2124871

+2

Si sta tentando di sostituire l'espressione con il valore calcolato in modo che il processore non debba ricalcolarlo per ogni riga. –

+0

Gotcha. Grazie per l'informazione - lo apprezzo. – user2124871

7

Utilizzo di lavori variabili;

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 

Il problema con il codice è che controlla che ciascuna parte funzioni quando viene passato un valore statico. Non mi piace che CHARINDEX(' ', 'Sara') - 1 risolva l'uguale a -1. Un trucco per aggirare questo sarebbe quello di avvolgere questa funzione nella funzione ABS();

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

Molto ben spiegato - Tra le due risposte, capisco cosa sta succedendo ora. Grazie per le informazioni. – user2124871