Sqlserver
 sql >> Base de données >  >> RDS >> Sqlserver

MS-SQL AND/OR est-il conditionnel (effectuer une évaluation de court-circuit) ?

Il n'y a aucune garantie de ce comportement.

Un exemple d'évaluation de court-circuit pas se passe avec expr1 AND expr2 est

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'

Le EXISTS(SELECT COUNT(*) FROM master..spt_monitor HAVING COUNT(*)=2) est false (c'est-à-dire And -ed l'expression doit être False ) mais les résultats de l'IO montrent que la deuxième condition était toujours évaluée.

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 peut fais ça quand même. Je vois ça dans mon 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'

La sortie est

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)

Affichage des spt_values n'a jamais été consulté.

Ceci est implémenté par une condition de prédicat de passage dans le plan d'exécution. Il y a quelques informations à leur sujet ici.

Si le prédicat passthru est évalué à true, la jointure renvoie la ligne.... Si le prédicat passthru est évalué à false, la jointure se poursuit normalement