SQL:短路不起作用。升级到SQL Server 2012后,“空或全文谓词”

时间:2013-12-13 10:57:24

标签: sql sql-server tsql stored-procedures sql-server-2012

我在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,因为我们多年来在多个项目中使用了这种技术在几十个存储过程中。

3 个答案:

答案 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)
...
  • 如果条件1为TRUE,是否会检查条件2?
  • 如果条件3为假,是否会检查条件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不会像在其他编程语言中那样进行短路操作,并且您无法强制执行此操作。