【问题标题】:SQL ignore part of WHERE if parameter is null如果参数为空,SQL 会忽略 WHERE 的一部分
【发布时间】:2013-07-25 06:36:12
【问题描述】:

我有一个基于 4 个参数从表中获取信息的存储过程。

我想根据参数获取值,但如果参数为 NULL,则不检查该参数。因此,如果所有 4 个参数都为 null,我将显示整个表格。

这是我的 SP(如您所见,这只适用于 1 个参数 atm):

CREATE PROCEDURE myProcedure
    @Param1 nvarchar(50),
    @Param2 nvarchar(50),
    @Param3 nvarchar(50),
    @Param4 nvarchar(50)
AS
BEGIN
    IF(@Param1 IS NULL)
        BEGIN
            SELECT Id, col1, col2, col3, col4 FROM myTable
        END
    ELSE
        BEGIN
            SELECT Id, col1, col2, col3, col4 FROM myTable WHERE col1 LIKE @Param1+'%'
        END
END

有没有办法做到这一点没有每个可能的组合(15 个 IF)都有一个IF

【问题讨论】:

标签: sql database sql-server-2008 stored-procedures


【解决方案1】:

怎么样

SELECT Id, col1, col2, col3, col4 
FROM    myTable 
WHERE   col1 LIKE @Param1+'%'
OR      @Param1 IS NULL

在这种特定情况下,您也可以使用

SELECT Id, col1, col2, col3, col4 
FROM    myTable 
WHERE   col1 LIKE ISNULL(@Param1,'')+'%'

但总的来说,您可以尝试类似的方法

SELECT Id, col1, col2, col3, col4 
FROM    myTable 
WHERE   (condition1 OR @Param1 IS NULL)
AND     (condition2 OR @Param2 IS NULL)
AND     (condition3 OR @Param3 IS NULL)
...
AND     (conditionN OR @ParamN IS NULL)

【讨论】:

  • 当心。 IS NULL 导致完整的扫描表访问。
  • 我得到了这个工作,但无法理解condition1@Param1 IS NULL 的情况下如何被忽略。我有以下条件(m.idAgent = agent OR agent is null)。如果我将 null 传递给 agent 参数,它只会返回所有代理。棒极了!你能解释一下吗?
  • 这是一个很好的解决方案,效果很好。谢谢!
  • 同样重要的是要注意 - 不保证表达式评估的顺序。也就是说,你不能依赖短路。见:blogs.msdn.microsoft.com/bartd/2011/03/03/…
  • 嗨@AmitChigadani,当您将NULL 传递给代理参数时,如果m.idAgent 为NULL,则m.idAgent = agent 将不为真。即您正在检查 NULL = NULL 是否为 False,因为 Null 不等于 Null。这就是表达式的第二部分(agent IS NULL)被执行的时候。希望对您有所帮助。
【解决方案2】:

您可以在 SQL Server 中使用 COALESCE() 函数。您不需要在语句中使用IF- ElseCASE。以下是使用COALESCEfunction 的方法。

SELECT Id, col1, col2, col3, col4 FROM myTable where col1 = COALESCE(NULLIF(@param1, ''), col1) and col2 = COALESCE(NULLIF(@param2, ''), col2) and col3 = COALESCE(NULLIF(@param3, ''), col3) and col4=
COALESCE(NULLIF(@param4, ''), col4)

SQL 中的COALESCE 函数返回其参数中的第一个非NULL 表达式。例如,如果 @param1 等于 null,则函数将返回 col1,这将导致 where 语句中的 col1=col1 类似于 1=1,表示条件始终为真。

【讨论】:

    【解决方案3】:
    CREATE PROCEDURE myProcedure
        @Param1 nvarchar(50),
        @Param2 nvarchar(50),
        @Param3 nvarchar(50),
        @Param4 nvarchar(50)
    AS
    BEGIN
        IF(@Param1 IS NULL)
            BEGIN
                SELECT Id, col1, col2, col3, col4 FROM myTable
            END
        ELSE
            BEGIN
                SELECT Id, col1, col2, col3, col4 FROM myTable WHERE col1 LIKE @Param1+'%' OR @Param1 is Null
            END
    END
    

    这应该会有所帮助

    问候

    阿舒托什·艾莉亚

    【讨论】:

    • 这是一个最简单的解决方案,但是对于长脚本,我必须一次又一次地编写长部分。 :(
    • 如果只有上述解决方案中的这个语句会怎样。 :- SELECT Id, col1, col2, col3, col4 FROM myTable WHERE (col1 LIKE @Param1+'%' OR @Param1 is Null) and ...
    【解决方案4】:

    如果您的意思是 @param1 是 col1 的参数,@param2 是 col2 的参数,... 等等 你可以试试这个:

    CREATE PROCEDURE myProcedure
    @Param1 nvarchar(50),
    @Param2 nvarchar(50),
    @Param3 nvarchar(50),
    @Param4 nvarchar(50)
    AS
    BEGIN
    declare @query nvarchar(4000)
    SET @query='SELECT Id, col1, col2, col3, col4 FROM myTable '+
        (case when ((@Param1 is null) and (@Param2 is null) and (@Param3 is null) and (@Param4 is null))
        then ''
        else
            'where '+
            (case when @Param1 is not null
            then ' col1 like '''+@param1+'%'''+
                (case when @param2 is not null then ' AND ' else '' end)
            else '' end)+
            (case when @Param2 is not null
            then ' col2 like '''+@param2+'%'''+
                (case when @param3 is not null then ' AND ' else '' end)
            else '' end)+
            (case when @Param3 is not null
            then ' col3 like '''+@param3+'%'''+
                (case when @param4 is not null then ' AND ' else '' end)
            else '' end)+
            (case when @Param4 is not null
            then ' col4 like '''+@param4+'%'''
            else '' end)
        end)
    
    exec sp_sqlexec @query
    

    【讨论】:

      【解决方案5】:
      Declare @criteria nvarchar (max)
      SELECT       col1,col2,col3
      FROM            table1
      ((col1+col2+col3 like '%'+@criteria+'%')  OR ISNULL(@criteria, '') = '')
      

      【讨论】:

        【解决方案6】:
        CREATE PROCEDURE myProcedure
          @Param1 nvarchar(50) **= '',**              //#1
          @Param2 nvarchar(50) **= '',**
          @Param3 nvarchar(50) **= '',**
          @Param4 nvarchar(50) **= ''**
        AS
        BEGIN
            **SET @Param1 = ISNULL(@Param1, '')**     //#2
        
            SELECT Id, col1, col2, col3, col4 FROM myTable WHERE col1 LIKE @Param1+'%' 
        END
        
        1. 为您的参数提供默认值(空字符串''):如果调用者跳过这些参数,您将收到一个空字符串,该字符串可以很好地与您的like 子句(例如myProcedure @Param4 = 'some value' // 在这种情况下,其他参数将被设置为空 string('') @param1 )
        2. 将 params 设置为 '' 以使自己免受 null 参数的影响(例如 myProcedure Param1 = null, @param2 = null ... // 在这种情况下 like 不会对 null 值起作用,并且不会为您提供针对参数,以避免对空值进行额外检查。

        【讨论】:

          【解决方案7】:

          至少对我来说,这将起作用并且更容易理解。 IIF 语句仅在 SQL Server 2012 及更高版本中可用,您可以将其替换为 case 语句。

          SELECT Id, col1, col2, ... 
          FROM    myTable 
          WHERE   condition1 = IIF(col1 IS NULL, col1, @Param1)
          AND     condition2 = IIF(col2 IS NULL, col2, @Param2)...
          

          【讨论】:

            【解决方案8】:

            在哪里添加条件并使用CASE .. WHEN .. THEN..

            尝试以下方式。

            select col1,col2,...colN..from Table 
            Where clm1 = CASE WHEN @PARAMETER = 0 THEN **COL1** ELSE **@PARAMETER** 
            

            一旦您在 WHERE 条件中设置了相同的列名,然后如果您想作为参数传递,则从表中检索所有数据,然后根据表中的条件值检索。

            【讨论】:

            • 这是对所有大写字母的不必要使用。重点是什么?你想强调什么?
            猜你喜欢
            • 2019-02-19
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2020-12-28
            • 1970-01-01
            • 2015-02-24
            • 1970-01-01
            • 2022-08-02
            相关资源
            最近更新 更多