web-dev-qa-db-fra.com

L'instruction SQL Server CASE évalue-t-elle toutes les conditions ou quitte-t-elle la première condition TRUE?

L'instruction SQL Server (2008 ou 2012, en particulier) CASE évalue-t-elle toutes les conditions WHEN ou se ferme-t-elle une fois qu'elle trouve une clause WHEN qui prend la valeur true? Si elle passe par l'ensemble des conditions, cela signifie-t-il que la dernière condition évaluée comme vraie écrase ce que la première condition évaluée comme vraie a fait? Par exemple:

SELECT
    CASE
        WHEN 1+1 = 2 THEN'YES'
        WHEN 1+1 = 3 THEN 'NO'
        WHEN 1+1 = 2 THEN 'NO' 
    END

Le résultat est "OUI", même si la dernière condition quand doit le faire évaluer à "NON". Il semble qu'il se termine une fois qu'il a trouvé la première condition VRAIE. Quelqu'un peut-il s'il vous plaît confirmer si c'est le cas.

45
Juan Velez

• Renvoie l'expression_résultat de la première expression_entrée = lorsque_expression qui est évaluée à VRAI .

Référence http://msdn.Microsoft.com/en-us/library/ms181765.aspx


Il s'agit d'un comportement SQL standard:

  • Une expression CASE évalue la première vraie condition.

  • S'il n'y a pas de véritable condition, il est évalué dans la partie ELSE.

  • S'il n'y a pas de véritable condition et pas de partie ELSE, elle est évaluée à NULL.

47
James Jenkins

SQL Server effectue généralement l'évaluation des courts-circuits pour les instructions CASE ( SQLFiddle ):

--Does not fail on the divide by zero.
SELECT 
   CASE 
      WHEN 1/1 = 1 THEN 'Case 1'
      WHEN 2/0 = 1 THEN 'Case 2'
   END;

--Fails on the divide by zero.
SELECT 
   CASE 
      WHEN 1/1 = 99 THEN 'Case 1'
      WHEN 2/0 = 99 THEN 'Case 2'
   END;  

Il existe cependant plusieurs types d'instructions qui, à partir de SQL Server 2012, ne court-circuitent pas correctement. Voir le lien de ypercube dans les commentaires.

Oracle effectue toujours l'évaluation des courts-circuits . Voir 11.2 Référence du langage SQL . Ou comparez les éléments suivants ( SQLFiddle ):

--Does not fail on the divide by zero.
SELECT
  CASE 
    WHEN 1/1 = 1 THEN 'Case 1'
    WHEN 2/0 = 1 THEN 'Case 2'
  END
FROM dual;


--Fails on the divide by zero.
SELECT
  CASE 
    WHEN 1/1 = 99 THEN 'Case 1'
    WHEN 2/0 = 99 THEN 'Case 2'
  END
FROM dual;

Ce même test ne peut pas être fait avec MySQL car il retourne NULL pour une division par zéro. ( SQL Fiddle )

15
Leigh Riffel

Il semble que MS SQL Server utilise également une évaluation de court-circuit.

Dans le test suivant, j'ai 3 tests. Le premier est toujours vrai, le second échoue sans référencer la table et le troisième échoue uniquement lorsque les données sont prises en compte.
Dans cette exécution particulière, les deux lignes sont renvoyées avec succès. Si je commente le premier QUAND, ou le premier et le deuxième, j'obtiens des échecs.

CREATE TABLE casetest (test varchar(10))
GO
INSERT INTO casetest VALUES ('12345'),('abcdef')
GO

SELECT CASE WHEN LEN(test)>1 THEN test
        WHEN 1/0 = 1 THEN 'abc'
        WHEN CAST(test AS int) = 1 THEN 'def'
        END
FROM casetest
GO
7
Kenneth Fisher

Dans MySQL, il quittera l'instruction case sur la première vraie option. Si vous avez la possibilité de plusieurs valeurs vraies, vous souhaitez placer la réponse préférée plus tôt dans la séquence.

1
Rob

si l'instruction case utilisée dans la condition WHERE et le premier cas où l'instruction impliquent l'évaluation des valeurs de colonne de la table et que la première ligne de la table ne remplit pas cette condition, l'instruction case passera au cas suivant lorsque déclaration.

declare @tbl table(id int)
insert into @tbl values(1)
insert into @tbl values(2)
insert into @tbl values(3)

--Fails on the divide by zero.
SELECT * FROM @tbl
where  CASE 
        WHEN id = 2 THEN 1 -- first row in table will not satisfy the condition
        WHEN 2/0 = 1 THEN 1
        ELSE 0
      END =1

-- when filter the records to only who will staisfy the first case when condition, it 
will not fail on the divide by zero
SELECT * FROM @tbl
where ID=2 and -- first row in table will  satisfy the condition
  CASE 
    WHEN id = 2 THEN 1
    WHEN 2/0 = 1 THEN 1
    ELSE 0
  END =1
1
abdelmoniem hafez