L'expression CASE évalue-t-elle tous les cas avant le traitement?

J'ai la requête suivante:

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 

Assez simple – je teste une requête de partage de nom. Donc, je teste le scénario où le nom n'a pas d'espaces et je reçois l'exception suivante:

Paramètre de longueur non valide transmis à la fonction SUBSTRING .

Pourquoi donc? Ne devrait-il pas évaluer la première clause et passer immédiatement à l' ELSE ? Comment puis-je contourner cela..?

L'optimiseur est assez intelligent pour remarquer que vous avez une expression constante et essayez de l'évaluer. Passer la constante à travers une variable la ferait tourner:

 DECLARE @TestSsortingng nvarchar(100) = 'Sara'; SELECT CASE WHEN @TestSsortingng like '% %' THEN SUBSTRING(@TestSsortingng, 1, CHARINDEX(' ', @TestSsortingng) - 1) ELSE @TestSsortingng END AS FirstName, CASE WHEN @TestSsortingng like '% %' THEN SUBSTRING(@TestSsortingng, CHARINDEX(' ', @TestSsortingng) + 1, 8000) ELSE '' END AS LastName 

Pour répondre à la question, le processeur ne calculerait THEN que si WHEN est vrai , sinon il calculera uniquement l'expression ELSE . Mais avant même que Optimizer ne tente de replace toutes les expressions constantes par des valeurs calculées, Processor ne devra pas les recalculer pour chaque ligne. C'est ce qu'on appelle " Constant Folding ".

En utilisant une variable fonctionne;

 DECLARE @NameSsortingng varchar(10); SET @NameSsortingng = 'Sara' SELECT CASE WHEN @NameSsortingng like '% %' THEN SUBSTRING(@NameSsortingng, 1, CHARINDEX(' ', @NameSsortingng) - 1) ELSE @NameSsortingng END AS FirstName, CASE WHEN @NameSsortingng like '% %' THEN SUBSTRING(@NameSsortingng, CHARINDEX(' ', @NameSsortingng) + 1, 8000) ELSE '' END AS LastName 

Le problème avec votre code est qu'il vérifie que chaque partie fonctionnera lorsqu'une valeur statique est transmise. Il n'aime pas que CHARINDEX(' ', 'Sara') - 1 résout égal à -1. Un hack pour contourner ce serait d'envelopper cette fonction dans la fonction 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