WHERE IS NULL、IS NOT NULL 或 NO WHERE 子句取决于 SQL Server 参数值

Posted

技术标签:

【中文标题】WHERE IS NULL、IS NOT NULL 或 NO WHERE 子句取决于 SQL Server 参数值【英文标题】:WHERE IS NULL, IS NOT NULL or NO WHERE clause depending on SQL Server parameter value 【发布时间】:2010-10-23 01:57:29 【问题描述】:

我在 SQL Server 2000 中有一个基于参数值执行搜索的存储过程。对于传入的参数之一,我需要一个不同的 WHERE 子句,具体取决于它的值 - 问题是这 3 个值将是 MyColumn

    IS NULL IS NOT NULL ANY VALUE (NULL AND NOT NULL)(基本上没有WHERE 子句)

我在想出正确的语法时遇到了一些心理障碍。这是否可以在一个选择语句中完成而不执行一些IF @parameter BEGIN ... END 分支?

【问题讨论】:

【参考方案1】:

以下是使用单个 WHERE 子句解决此问题的方法:

WHERE (@myParm = value1 AND MyColumn IS NULL)
OR  (@myParm = value2 AND MyColumn IS NOT NULL)
OR  (@myParm = value3)

CASE 语句的幼稚用法不起作用,我的意思是:

SELECT Field1, Field2 FROM MyTable
WHERE CASE @myParam
    WHEN value1 THEN MyColumn IS NULL
    WHEN value2 THEN MyColumn IS NOT NULL
    WHEN value3 THEN TRUE
END

可以使用 case 语句解决此问题,请参阅 onedaywhen 的 answer

【讨论】:

你的想法和我一样。但是,您确实需要括号。 我不确定您是否需要括号,但我非常支持在复杂的布尔表达式中使用括号。如果你问我,没有它们让编译器来执行操作顺序,这相当可怕。 我已经尝试过 CASE 语句,但 CASE 计算为一个结果表达式,因此计算为 'IS NULL'、'IS NOT NULL'、'myColumn IS NULL' 等不起作用。现在只是测试你的第一个答案 我也试过了,CASE 不能这样工作。因此,我建议使用 CASE 语句来解决这个问题(见我的回答)是错误的。 我没想过这样做。现在我需要去修复我的一些存储过程...谢谢【参考方案2】:

你可以这样做:

SELECT *
FROM foo
WHERE (@param = 0 AND MyColumn IS NULL)
OR (@param = 1 AND MyColumn IS NOT NULL)
OR (@param = 2)

类似的东西。

【讨论】:

假设我需要按字符串过滤。如果字符串为空,我应该返回表中的所有记录,如果它不为空,我应该返回与字符串或部分字符串匹配的所有记录(LIKE 运算符)。你会怎么解决这个问题?【参考方案3】:

这就是使用CASE 的方法:

DECLARE @myParam INT;
SET @myParam = 1;

SELECT * 
  FROM MyTable
 WHERE 'T' = CASE @myParam
             WHEN 1 THEN 
                CASE WHEN MyColumn IS NULL THEN 'T' END
             WHEN 2 THEN
                CASE WHEN MyColumn IS NOT NULL THEN 'T' END
             WHEN 3 THEN 'T' END;

【讨论】:

【参考方案4】:
WHERE MyColumn = COALESCE(@value,MyColumn) 

如果@valueNULL,它将比较MyColumn 与自己,忽略 @value = no where 子句。

如果 @value 有一个值 (NOT NULL),它会将 MyColumn@value

参考: COALESCE (Transact-SQL)。

【讨论】:

我不相信您可以在这种情况下使用 CASE 语句,因为 CASE 评估为一个结果表达式。 COALESCE 甚至 ISNULL 我也不相信会起作用。 请查看我的编辑,我是否完全遗漏了您的问题中的某些内容? @Deviant - 我认为您稍微错过了这个问题。 MyColumn 上的 WHERE 子句需要由另一个值设置,因为它与参数值不直接相关,即如果传递 NULL,则 WHERE 子句被否定。如果传递了任何其他值,则结果集将仅用于 WHERE MyColumn 等于该值,而不是具有已知值的 MyColumn。未解决具有 NULL 值的 MyColumn 的 WHERE 子句。 这就是使用 COALESCE 的工作方式,这不是我需要的 假设我需要按字符串过滤。如果字符串为空,我应该返回表中的所有记录,如果它不为空,我应该返回与字符串或部分字符串匹配的所有记录(LIKE 运算符)。你会怎么解决这个问题?【参考方案5】:

CASE的另一种方式:

SELECT *  
FROM MyTable
WHERE 1 = CASE WHEN @myParm = value1 AND MyColumn IS NULL     THEN 1 
               WHEN @myParm = value2 AND MyColumn IS NOT NULL THEN 1 
               WHEN @myParm = value3                          THEN 1 
          END

【讨论】:

【参考方案6】:

我在这个解决方案上取得了成功。这几乎就像帕特里克的,有点扭曲。您可以单独或按顺序使用这些表达式。如果参数为空,它将被忽略并显示您搜索的列的所有值,包括 NULLS。

SELECT * FROM MyTable
WHERE 
    --check to see if @param1 exists, if @param1 is blank, return all
    --records excluding filters below
(Col1 LIKE '%' + @param1 + '%' OR @param1 = '')
AND
    --where you want to search multiple columns using the same parameter
    --enclose the first 'OR' expression in braces and enclose the entire 
    --expression 
((Col2 LIKE '%' + @searchString + '%' OR Col3 LIKE '%' + @searchString + '%') OR @searchString = '')
AND
    --if your search requires a date you could do the following
(Cast(DateCol AS DATE) BETWEEN CAST(@dateParam AS Date) AND CAST(GETDATE() AS DATE) OR @dateParam = '')

【讨论】:

【参考方案7】:

这种逻辑可以使用EXISTS实现:

CREATE TABLE tab(a INT, b VARCHAR(10));
INSERT INTO tab(a,b) VALUES(1,'a'),(1, NULL),(NULL, 'a'),(2,'b');

查询:

DECLARE @a INT;

--SET @a = 1;    -- specific NOT NULL value
--SET @a = NULL; -- NULL value
--SET @a = -1;   -- all values

SELECT *
FROM tab t
WHERE EXISTS(SELECT t.a INTERSECT SELECT @a UNION SELECT @a WHERE @a = '-1');

db<>fiddle demo

它可以扩展为包含多个参数:

SELECT *
FROM tab t
WHERE EXISTS(SELECT t.a INTERSECT SELECT @a UNION SELECT @a WHERE @a = '-1')
  AND EXISTS(SELECT t.b INTERSECT SELECT @b UNION SELECT @a WHERE @b = '-1');

【讨论】:

以上是关于WHERE IS NULL、IS NOT NULL 或 NO WHERE 子句取决于 SQL Server 参数值的主要内容,如果未能解决你的问题,请参考以下文章

Where is the Marble?

10474 - Where is the Marble?(模拟)

Where is NuGet in VS2017 Community?

Where is the bug and how is it fixed? an experiment with practitioner's

Where is the python library installed?

UVA - 10474 Where is the Marble?(排序)