使用CASE的SQL设置WHERE语句使用add运算符放置错误

问题描述

在下面的脚本中,仅在设置了CASE的情况下,我才想设置WHERE语句。

struct MutableStruct
{
    public int I { get; set; }
}

var m = new mutableStruct();
Foo(m);
var b = m.I == 1; //false!

void Foo(MutableStruct mutableStruct) { mutableStruct.I = 1; } 

但是我得到了错误

添加运算符中,数据类型varchar和binary不兼容

解决方法

您似乎使事情变得过于复杂。您在这里不需要动态语句,也不需要2个参数。使用单个参数,如果不想使用它,则传递值NULL。这就是所谓的“追赶”或“厨房水槽”查询:

DECLARE @Date date = '20200314'; --Notice it is NOT a varchar

SELECT {Your Columns} --Replace this with a list of your columns
FROM dbo.YourTable --Replace this with your actual schema and table
WHERE [Changed At] >= @Date --Ideally,don't use names that must be delimit Identified
   OR @Date IS NULL
OPTION (RECOMPILE);

OPTION (RECOMPILE)可以停止缓存错误的计划,好像@Date的值为NULL一样,则需要进行全表扫描,但是如果不是这样(取决于在您的索引上)可能不需要,可能会更快。由于查询非常简单,因此重新生成查询计划的开销可以忽略不计,并且成本可能

,

看来您已经使解决方案复杂化了。为什么不尝试呢?

SELECT *
FROM [Table]
WHERE @dowhere = 0
      OR [Changed At] >= @date;

但是,最好将@dowhere的数据类型改为BIT而不是BINARY

,

您的做法很愚蠢。如果不需要过滤,请完全删除case中的where

set @cmdINSERT = '
SELECT *
FROM [TABLE]
[where]';

SET @cmdInsert = REPLACE(@cmdInsert,'[where]',(CASE WHEN @dowwhere = 1
                               THEN 'WHERE [Changed At] = @date'
                               ELSE ''
                          END)
                         );
exec sp_executesql @cmdInsert,N'@date date',@date=@date;

请注意,这也正确将日期作为参数传递,而不是浪费查询字符串。如果不使用date参数,那很好:SQL Server只会忽略不使用的参数。