14

我正在创建一个存储过程来返回搜索结果,其中某些参数是可选的。

我想在where子句中添加“if 语句”,但无法正常工作。where子句应仅按非空参数过滤。

这里是sp

ALTER PROCEDURE spVillaGet 
-- Add the parameters for the stored procedure here
@accomodationFK int = null,
@regionFK int = null,
@arrivalDate datetime,
@numberOfNights int,
@sleeps int = null,
@priceFloor money = null,
@priceCeil money = null
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;

-- Insert statements for procedure here
select tblVillas.*, tblWeeklyPrices.price from tblVillas
INNER JOIN tblWeeklyPrices on tblVillas.villaId = tblWeeklyPrices.villaFK
where 
    If @accomodationFK <> null then
        accomodationTypeFK = @accomodationFK 
     @regionFK <> null Then
        And regionFK = @regionFK 
    IF @sleeps <> null Then
        And sleeps = @sleeps 
    IF @priceFloor <> null Then
        And price >= @priceFloor And price <= @priceCeil


END

任何想法如何做到这一点?

4

5 回答 5

25
select tblVillas.*, tblWeeklyPrices.price 
from tblVillas
INNER JOIN tblWeeklyPrices on tblVillas.villaId = tblWeeklyPrices.villaFK
where (@accomodationFK IS null OR accomodationTypeFK = @accomodationFK)
  AND (@regionFK IS null or regionFK = @regionFK)
  AND (@sleeps IS null OR sleeps = @sleeps)
  AND (@priceFloor IS null OR (price BETWEEN @priceFloor And @priceCeil))
于 2008-11-25T13:48:36.840 回答
1

过去我们在这里使用了很多COALESCE动态 WHERE 子句”,就像你在说的那样。

SELECT *
FROM  vehicles
WHERE ([vin]   LIKE COALESCE(@vin, [vin])     + '%' ESCAPE '\')
  AND ([year]  LIKE COALESCE(@year, [year])   + '%' ESCAPE '\')
  AND ([make]  LIKE COALESCE(@make, [make])   + '%' ESCAPE '\')
  AND ([model] LIKE COALESCE(@model, [model]) + '%' ESCAPE '\')

但是,当您想要选择性地过滤一个也可以为空的列时,就会出现一个大问题......如果列中的数据是null给定行的,并且用户没有输入任何内容来搜索该列(所以用户输入也是null),那么该行甚至不会出现在结果中(如果您的过滤器是可选的,则它是不正确的排除行为)。

为了补偿可空字段,您最终不得不像这样执行看起来更混乱的 SQL:

SELECT *
FROM  vehicles
WHERE (([vin]   LIKE COALESCE(@vin, [vin])     + '%' ESCAPE '\')
       OR (@vin IS NULL AND [vin] IS NULL))
  AND (([year]  LIKE COALESCE(@year, [year])   + '%' ESCAPE '\')
       OR (@year IS NULL AND [year] IS NULL))
  AND (([make]  LIKE COALESCE(@make, [make])   + '%' ESCAPE '\')
       OR (@make IS NULL AND [make] IS NULL))
  AND (([model] LIKE COALESCE(@model, [model]) + '%' ESCAPE '\')
       OR (@model IS NULL AND [model] IS NULL))
于 2008-11-25T14:16:56.860 回答
0

您还可以使用 IsNull 或 Coalesce 函数

Where accomodationTypeFK = IsNull(@accomodationFK, accomodationTypeFK)
    And regionFK = Coalesce(@regionFK,regionFK)
    And sleeps = IsNull(@sleeps,sleeps ) 
    And price Between IsNull(@priceFloor, Price) And IsNull(priceCeil, Price)  

这与迈克尔上面的建议相同......

IsNull() 和 Coalesce() 的工作方式或多或少相同,它们返回列表中的第一个非 Null 参数,除了 iSNull 只允许 2 个参数,并且 Coalesce 可以采用任何数字...

http://blogs.msdn.com/sqltips/archive/2008/06/26/differences-between-isnull-and-coalesce.aspx

于 2008-11-25T13:59:49.687 回答
0

正如你所理解的,IF 是 T-SQl 中的程序代码。它不能用于插入/更新/删除/选择语句中,它只能用于确定要运行的两个语句中的哪一个。当你在一个语句中需要不同的可能性时,你可以像上面那样做或使用 CASE 语句。

于 2008-11-25T14:35:42.483 回答
-2

尝试将 IF 语句放在整个 SQL 语句周围。这意味着每个条件都有一个 SQL 语句。这对我有用。

于 2009-12-30T17:54:09.560 回答