回答

收藏

SQL分配变量与子查询

技术问答 技术问答 280 人阅读 | 0 人回复 | 2023-09-14

我对以下2条SQL有疑问:  v0 `) U. {7 y% `" z' u
declare @i1 bit, @b1 bit' K; v9 T* B' r2 `8 @) R
declare @i2 bit, @b2 bit% c4 K8 p1 H% v; Q3 H- b3 ~
declare @t table (Seq int)6 X9 u3 K8 V/ F3 Q+ Q# B* B
insert into @t values (1)2 T( t* p1 f+ y5 D! f) U3 E  r- J
-- verify data; C8 s8 O. d9 r) }2 i2 l1 q0 m' Y( c
select case when (select count(1) from @t n2 where 1 = 2) > 0 then 1 else 0 end
; q/ N2 X4 L, b( n9 g-- result 0
# B" H) j: @3 wselect @i1 = 1, @b1 = case when @i1 = 1 or ((select count(1) from @t n2 where 1 = 2) > 0) then 1 else 0 end from @t n where n.Seq = 15 m9 c$ q1 P1 O' h% I
select @i1, @b1
! L9 n+ w- X! V6 V& Q-- result 1, 0
8 p' @/ p0 d! L) Y" sselect @i2 = 1, @b2 = case when @i2 = 1 or (0 > 0) then 1 else 0 end from @t n where n.Seq = 1
, W5 x& r6 g# ?: u' gselect @i2, @b2: c% i2 D% S0 C1 J4 y
-- result 1, 1, b& R2 T( J1 ~
SQL小提琴在这里
& |+ M  [% p, ]# u  Q在执行之前,我认为案例部分应该是null = 1 or (0 > 0),它将返回0。
; Z! E& E% t" ]$ S" T. [- h! G但是现在,我想知道为什么第二个SQL会返回1
% q. W% |- I" p1 W3 U# t5 _               
6 O8 z8 K2 K" {4 }$ H8 c解决方案:
- c; J% t' f1 o( T6 P0 N$ I                : P1 l1 z" c1 h1 U; o
7 P6 v% e, C5 n9 e7 d( H; F
! N8 _2 a& a0 Z8 S# u, \
                我将其作为答案发布,因为它来自Training Kit (70-461):
7 F3 ~5 e; u- B8 Q8 O- Q$ S
5 i6 Y6 n6 i; j) rWHERE propertytype = 'INT' AND CAST(propertyval AS INT) > 10
$ Y5 z* j3 Y3 A. b2 @1 |一些人假设除非优先级规则另有规定,否则谓词将从左到右进行评估,并且在可能的情况下会发生短路。换句话说,如果第一个谓词属性类型=’INT’的评估结果为false,则SQL& u* n; v0 h6 e8 [3 f1 r
Server将评估第二个谓词CAST(propertyval AS INT)>/ \+ _% W+ D3 |) |% @- A! i
10,因为结果是已知的。基于此假设,期望查询永远不会失败,无法进行可转换的转换。6 g+ x3 p, D0 X6 N. Y3 r, E- M
但是,现实是不同的。SQL Server在内部支持短路概念。但是,由于 语言中的 概念一次性
6 ^; i6 z0 V6 O( X6 V3 c; p的,因此不一定要按从左到右的顺序评估表达式。它可以基于成本相关的原因决定从第二个表达式开始,然后如果第二个表达式的计算结果为true,则也要对第一个表达式进行评估。这意味着,如果表中存在属性类型不同于“% e+ V8 {9 V+ T# k$ O) U5 U
INT”的行,并且在这些行中propertyval不能转换为INT,则由于转换错误,查询可能会失败。
分享到:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则