运行 服务器 2019 上的意外订单 运行 OR 运算符
Unexpected order running OR operator on SQL Server 2019
我在从 SQL Server 2008 R2 迁移到 SQL Server 2019 时遇到问题。
我的代码
DECLARE @str NVARCHAR(50) = 'all',
@int TINYINT = 1
DECLARE @tmp TABLE (val nvarchar(MAX))
INSERT INTO @tmp VALUES('123')
INSERT INTO @tmp VALUES('all')
SELECT val
FROM @tmp
WHERE @str = 'ALL' OR @int = val
使用SQL Server 2008 R2 时,没问题。如下所示的预期输出
val
123
all
但是,当我迁移到SQL Server 2019 时,出现如下错误。再说了,这在2019年也是不寻常的。
Msg 245 Level 16 State 1 Line 8 Conversion failed when converting the
nvarchar value 'all' to data type int.
如您所见,第二种情况 OR @int = val
意外发生。
我想知道它是否由于与 OR
运算符 或 case sensitive
[= 的顺序相关的任何重大更改而失败39=] ALL
vs all
在下一个 SQL Server 2008 R2 版本中。
已更新
抱歉,我的重现代码让你们感到困惑。 This is my original code
你应该做这三件事中的两件事:
(
要么使用DECLARE @int nvarchar(max) = 1
或
使用WHERE val = CONVERT(nvarchar(max), @int)
)
和
- 更改为使用
STRING_SPLIT
。即使在本机解决方案存在之前,循环函数也是您可以用来拆分字符串的效率最低的方法之一。参见 https://sqlblog.org/split
这个db<>fiddlefiddle演示。
和 this one 说明了为什么 WHERE @str = 'ALL' OR (@str <> 'ALL' AND @int = val)
不是解决方案。您选择的这些模式仅在 @str
是 总是 'all'
时才有效,因为它们在其他任何情况下都会中断。那么为什么要有 OR
呢?
您一直坚持 SQL 服务器应该服从从左到右的评估,但我们一直告诉您事实并非如此。
这里是 an article by Bart Duncan at Microsoft,他在 SQL 服务器上工作,在发表更多评论或进一步编辑您的问题之前,您绝对应该完整阅读。不过,关键点是:
You cannot depend on expression evaluation order for things like
WHERE <expr1> OR <expr2>
since the optimizer might choose a plan that evaluates the second predicate before the first one.
我在从 SQL Server 2008 R2 迁移到 SQL Server 2019 时遇到问题。 我的代码
DECLARE @str NVARCHAR(50) = 'all',
@int TINYINT = 1
DECLARE @tmp TABLE (val nvarchar(MAX))
INSERT INTO @tmp VALUES('123')
INSERT INTO @tmp VALUES('all')
SELECT val
FROM @tmp
WHERE @str = 'ALL' OR @int = val
使用SQL Server 2008 R2 时,没问题。如下所示的预期输出
val
123
all
但是,当我迁移到SQL Server 2019 时,出现如下错误。再说了,这在2019年也是不寻常的。
Msg 245 Level 16 State 1 Line 8 Conversion failed when converting the nvarchar value 'all' to data type int.
如您所见,第二种情况 OR @int = val
意外发生。
我想知道它是否由于与 OR
运算符 或 case sensitive
[= 的顺序相关的任何重大更改而失败39=] ALL
vs all
在下一个 SQL Server 2008 R2 版本中。
已更新
抱歉,我的重现代码让你们感到困惑。 This is my original code
你应该做这三件事中的两件事:
(
要么使用
DECLARE @int nvarchar(max) = 1
或
使用
WHERE val = CONVERT(nvarchar(max), @int)
)
和
- 更改为使用
STRING_SPLIT
。即使在本机解决方案存在之前,循环函数也是您可以用来拆分字符串的效率最低的方法之一。参见 https://sqlblog.org/split
这个db<>fiddlefiddle演示。
和 this one 说明了为什么 WHERE @str = 'ALL' OR (@str <> 'ALL' AND @int = val)
不是解决方案。您选择的这些模式仅在 @str
是 总是 'all'
时才有效,因为它们在其他任何情况下都会中断。那么为什么要有 OR
呢?
您一直坚持 SQL 服务器应该服从从左到右的评估,但我们一直告诉您事实并非如此。
这里是 an article by Bart Duncan at Microsoft,他在 SQL 服务器上工作,在发表更多评论或进一步编辑您的问题之前,您绝对应该完整阅读。不过,关键点是:
You cannot depend on expression evaluation order for things like
WHERE <expr1> OR <expr2>
since the optimizer might choose a plan that evaluates the second predicate before the first one.