Sqlserver
 sql >> Base de Dados >  >> RDS >> Sqlserver

O MS-SQL AND/OR é condicional (realizar avaliação de curto-circuito)?


Não há garantia deste comportamento.

Um exemplo de avaliação de curto-circuito não acontecendo com expr1 AND expr2 é
SET STATISTICS IO ON

IF EXISTS(SELECT COUNT(*) FROM master..spt_monitor HAVING COUNT(*)=2)  
AND EXISTS (SELECT COUNT(*) FROM master..spt_values HAVING COUNT(*)=1)
PRINT 'Y'

O EXISTS(SELECT COUNT(*) FROM master..spt_monitor HAVING COUNT(*)=2) é false (significando o And -ed expressão deve ser False ), mas os resultados de IO mostram que a segunda condição ainda foi avaliada.
Table 'spt_values'. Scan count 1, logical reads 14, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'spt_monitor'. Scan count 1, logical reads 1, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

SQL Server pode faça isso embora. Eu vejo isso no meu teste
SET STATISTICS IO ON

DECLARE @p1 BIT = NULL

IF ( @p1 = 1
     AND EXISTS(SELECT *
                FROM   master..spt_values) )
  PRINT '1'

ELSE IF ( @p1 = 0
     AND EXISTS(SELECT *
                FROM   master..spt_values) )
  PRINT '2'

A saída é
Table 'Worktable'. Scan count 0, logical reads 0, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

(1 row(s) affected)
Table 'Worktable'. Scan count 0, logical reads 0, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

(1 row(s) affected)

Mostrando spt_values nunca foi acessado.

Isso é implementado por uma condição de predicado de passagem no plano de execução. Há algumas informações sobre eles aqui.

Se o predicado de passagem for avaliado como true, a junção retornará a linha.... Se o predicado de passagem for avaliado como falso, a junção prosseguirá normalmente