SQL 服务器中的 ALL IF Null 逻辑

ALL IF Null logic in SQL Server

我们需要在网页中实现搜索功能。所以我们创建了一个存储过程来检索记录。 逻辑是,当 i select 输入参数 Sp returns 参数的过滤记录时,它会检索所有可用记录。

例如:如果我给,

EXEC [WB_GetClassesByLocation_new2] null,null,null,'null',null,NULL,'N','N','N','N','N','N','N',NULL,null,null,null,null,null

(N 是天数字段的默认值) SP 将 return 所有可用的记录。 如果我给,

EXEC [WB_GetClassesByLocation_new2] 1000,null,null,'null',null,NULL,'N','N','N','N','N','N','N',NULL,null,null,null,null,null。 SP 将 return 区 1000 的记录。我已经实现了以下逻辑

Select distinct c.classID, co.fCourseName as CourseName, StreetAddress + ', ' + l.City as LocationAddress, s.SessionName, sh.fShift as shift, StartTime, EndTime, c.classname, s.SessionID,
        c.StartDate,c.enddate 
        From dbo.vw_Class c 
        Inner Join dbo.lk_Session s 
        On (s.SessionID = c.sessionID) 
        Inner Join dbo.lk_Course co 
        On (co.CourseID = c.CourseID )
        Inner Join dbo.vw_Location l 
        On (l.locationid = c.locationid) 
        Inner Join lk_District d
        On (d.districtID = c.districtId) 
        Inner Join lk_Province p 
        On (p.provik = d.provik) 
        Inner Join lk_Shift sh 
        On (c.shiftid = sh.shiftid)
       where 
          c.DistrictID       =  case  when @Districtid is null   then c.DistrictID   else  @Districtid  end 
         and c.LocationID    =  case  when @locationid is null   then c.LocationID   else  @locationid  end 
         and s.SessionID     =  case  when @sessionid is null    then s.SessionID    else  @sessionid   end 
         and c.CourseID      =  case  when @levelid  is null     then c.CourseID     else  @levelid     end 
         and c.ShiftID       =  case  when @shiftid   is null    then c.ShiftID      else  @shiftid     end 
         and c.StartDate    >=  case  when @startdate is null    then c.StartDate    else  @startdate   end
         and c.EndDate      <=  case when  @enddate is null      then c.EndDate      else  @enddate     end
         and convert(time,c.StartTime) >= case when @starttime is null then convert(time,c.StartTime) else convert(time,@starttime) end
         and convert(time,c.endtime)   <= case when @endtime is null then convert(time,c.endtime) else convert(time,@endtime) end
         and c.Monday    = case  when @day1 = 'N' then c.monday     else  @day1  end 
         and c.Tuesday   = case  when @day2 = 'N' then c.Tuesday        else  @day2  end 
         and c.Wednesday = case  when @day3 = 'N' then c.Wednesday  else  @day3  end 
         and c.Thursday  = case  when @day4 = 'N' then c.Thursday       else  @day4  end 
         and c.Friday    = case  when @day5 = 'N' then c.Friday     else  @day5  end 
         and c.Saturday  = case  when @day6 = 'N'then c.Saturday        else  @day6  end 
         and c.Sunday    = case  when @day7 = 'N' then c.Sunday     else  @day7  end 
         and c.RowStatus    = 'A' 
         ORDER BY co.fCourseName, s.SessionID ,c.ClassName

但是 Sp 的执行时间太长了。这是在 sql 服务器中实现 "All IF null" 逻辑的正确方法吗?还有其他方法可以做到吗?

这是我的做法:

( @Districtid is null OR c.DistrictID = @Districtid )
AND
( @Locationid is null OR c.LocationID = @Locationid )
AND
...

但是,当您拥有非常多的此类过滤器,并且已经足够接近我要试验的临界点时,您最好创建一个动态 SQL 查询。

当你有很多过滤器的查询时,我知道 2 个选项:

  1. 使用 OR(如上建议),这会导致查询优化器扫描 table。 请参阅此 post 了解更多信息:How to Optimize the Use of the "OR" Clause When Used with Parameters (SQL Server 2008)

  2. 使用动态 SQL - 这会导致查询优化器根据每个参数的每个变化计算执行计划 一个好的选择是使用动态 sql 和 Bind Variables, 这样优化器将缓存查询和执行计划。

    declare @sql varchar(500)
    DECLARE @ParmDefinition nvarchar(500);
    
    SET @sql='select * from a where 1=1 '
     if @Locationid  is null
    set @sql=@sql +' and @LocationId is null'
     else
     set @sql=@sql +' and LocationID= @LocationId'
    
      EXECUTE sp_executesql @sql, N'@LocationId int',
                  @LocationID ;