Sqlserver
 sql >> Database >  >> RDS >> Sqlserver

MS-SQL AND/OR è condizionale (esegue la valutazione del cortocircuito)?

Non vi è alcuna garanzia di questo comportamento.

Un esempio di valutazione del cortocircuito non succede con 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'

Il EXISTS(SELECT COUNT(*) FROM master..spt_monitor HAVING COUNT(*)=2) è false (che significa il And -ed l'espressione deve essere False ) ma i risultati IO mostrano che la seconda condizione è stata ancora valutata.

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 può fallo però. Lo vedo nel mio test

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'

L'output è

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)

Visualizzazione di spt_values non è mai stato effettuato l'accesso.

Ciò è implementato da una condizione predicativa pass-through nel piano di esecuzione. Ci sono alcune informazioni su questi qui.

Se il predicato passthru restituisce true, il join restituisce la riga.... Se passthrupredicate restituisce false, il join procede normalmente