我在SQL Server 2005中有以下查询可以正常工作:
DECLARE @venuename NVARCHAR(100)
DECLARE @town NVARCHAR(100)
SET @venuename = NULL -- normally these are parameters in the stored proc.
SET @town = 'London'
SELECT COUNT(*) FROM dbo.Venue
WHERE
(@VenueName IS NULL OR CONTAINS((Venue.VenueName), @VenueName))
AND
(@Town IS NULL OR Town LIKE @Town + '%')
当为参数传递空值时,它会使用短路(实际SP中的数量比我的示例中显示的要多)。
然而,在升级到SQL 2012之后,为@VenueName传递NULL并运行此查询失败,并显示错误“空或全空谓词”,因为SQL Server似乎正在运行(或评估) @VenueName的CONTAINS语句,即使@VenueName设置为NULL也是如此。
有没有办法在2012年使用短路或这是不可能的?我不想重写我的所有SP,因为我们多年来在多个项目中使用了这种技术在几十个存储过程中。
答案 0 :(得分:3)
我对sql 2012了解不多,但请你试试
DECLARE @venuename NVARCHAR(100)
DECLARE @town NVARCHAR(100)
SET @venuename = '""' -- -- **Yes '""' instead of null**.
SET @town = 'London'
SELECT COUNT(*) FROM dbo.Venue
WHERE
(@VenueName ='""' OR CONTAINS((Venue.VenueName), @VenueName))
AND
(@Town IS NULL OR Town LIKE @Town + '%')
答案 1 :(得分:1)
查看此主题:OR Operator Short-circuit in SQL Server在SQL Server中,无法保证OR子句提前中断。它总是这样,所以我猜你很幸运它与SQL Server 2005一起工作。
要解决您的问题,请考虑每次向CONTAINS函数提供可能为NULL的参数值时使用ISNULL函数。
答案 2 :(得分:-2)
这是完美答案。
我们来看看这两个陈述:
IF (CONDITION 1) OR (CONDITION 2)
..
IF (CONDITION 3) AND (CONDITION 4)
...
WHERE上的条件怎么样?SQL Server引擎是否优化了WHERE
子句中的所有条件?程序员是否应按正确的顺序放置条件以确保SQL Server优化器以正确的方式解析它?
增加:
感谢Jack的链接,感谢t-sql代码:
IF 1/0 = 1 OR 1 = 1
SELECT 'True' AS result
ELSE
SELECT 'False' AS result
IF 1/0 = 1 AND 1 = 0
SELECT 'True' AS result
ELSE
SELECT 'False' AS result
在这种情况下,没有提出除零除外。
结论:
如果C ++ / C#/ VB有短路,为什么SQL Server不能拥有它?
要真正回答这个问题,我们来看看两者是如何处理条件的。 C ++ / C#/ VB都有语言规范中定义的短路,以加快代码执行速度。当第一个条件已经为真时,为什么还要考虑N OR条件,或者当第一条条件已经为假时,为什么要考虑N AND条件。
我们作为开发人员必须意识到SQL Server的工作方式不同。这是一个基于成本的系统。为了获得查询的最佳执行计划,查询处理器必须评估每个where条件并为其分配成本。然后将这些成本作为一个整体进行评估,以形成一个阈值,该阈值必须低于SQL Server对良好计划所定义的阈值。如果成本低于定义的阈值,则使用该计划,如果不是,则使用不同的条件成本组合再次重复整个过程。这里的成本是扫描或搜索或合并连接或散列连接等...因此,C ++ / C#/ VB中的短路是不可能的。您可能认为强制在列上使用索引会计为短路但不会。它只强制使用该索引,并缩短可能的执行计划列表。该系统仍以成本为基础。
作为开发人员,您必须意识到SQL Server不会像在其他编程语言中那样进行短路操作,并且您无法强制执行此操作。