条件where子句T-SQL

时间:2011-09-23 15:44:14

标签: tsql sql-server-2008

我有一个返回数据的存储过程。

我需要根据传入的参数更改where子句。

例如,参数是:

@Region NVARHCAR(15)
@CountryCode NVARCHAR(2)
@ProductA BIT
@ProductB BIT
@ProductC BIT

如果传入@Region,则应按区域选择where,如果传入@CountryCode,则应按国家/地区代码选择where。

对于产品,如果其中任何一个设置为true,那么应该选择该项目的数据。

因此,如果传入@Region并且@ProductA和@ProductC设置为true,则该语句可能如下所示:

SELECT *
FROM table
WHERE Region = @Region AND
(Product = 'ProductA' OR Product = 'ProductC')

或者,有条件的产品可以是IN语句。

如果传入了@CountryCode,它将如下所示:

SELECT *
FROM table
WHERE CountryCode = @CountryCode AND
(Product = 'ProductA' OR Product = 'ProductC')

甚至可以传入@CountryCode和@Region。

有没有办法用T-SQL执行此操作,而不是从应用程序生成动态SQL?

由于

6 个答案:

答案 0 :(得分:6)

您不需要构建动态SQL语句,只需要检查参数的值即可。以下是我通常构建SQL子句来实现此目的的方法:

WHERE ((@Region IS NULL) OR (Region = @Region))
AND ((@CountryCode IS NULL) OR (CountryCode = @CountryCode))
AND ((@ProductA = 0) OR (Product = 'ProductA'))
AND ((@ProductB = 0) OR (Product = 'ProductB'))
AND ((@ProductC = 0) OR (Product = 'ProductC'))

如果您的SQL是这样构建的,那么当您传入@Region参数的值时,您只会在Region列上进行过滤。 CountryCode也是如此。

答案 1 :(得分:2)

这不一定是最干净的方法,但会避免任何动态:

SELECT *
FROM table
WHERE CountryCode = isnull(@CountryCode, CountryCode) AND
Region = isnull(@Region, Region) AND
(Product = 'ProductA' OR Product = 'ProductC')

答案 2 :(得分:2)

我会为每个案例简化并编写一个存储过程。或者至少添加程序逻辑:

如果不是@Region是空的     ....

并且有单独的查询,可以根据自己的优点进行优化。

编辑:

A couple principles that I think apply:

http://en.wikipedia.org/wiki/Coupling_%28computer_programming

http://en.wikipedia.org/wiki/Single_responsibility_principle

答案 3 :(得分:2)

您始终可以使用条件将SQL语句构建为字符串。然后使用sp_executesql执行生成的语句字符串(基本上执行可以多次重用的Transact-SQL语句或批处理的命令) ,或者是动态构建的......)

我知道你可能不想构建sql字符串,但它是一个解决方案。

答案 4 :(得分:1)

如果有的话,最直接的方法(不一定是最优雅的)是为每个参数设置一个非有效参数值的默认值,并对每个参数执行条件检查查看每个参数中包含的值是否与默认值不同。在这里,我假设null值永远不会作为有效值传入。

CREATE PROC sp_ProdInfo (
 @Region NVARHCAR(15) = NULL,
 @CountryCode NVARCHAR(2) = NULL,
 @ProductA BIT,
 @ProductB BIT,
 @ProductC BIT
) 
AS
 BEGIN
 -- other statements
 IF NOT @Region IS NULL
  BEGIN
   SELECT *
    FROM table
    WHERE Region = @Region AND
    (Product = 'ProductA' OR Product = 'ProductC')
  END
 ELSE
  BEGIN
   IF NOT @Country IS NULL
   BEGIN
    SELECT *
     FROM table
     WHERE CountryCode = @CountryCode AND
     (Product = 'ProductA' OR Product = 'ProductC')
   END
   ELSE
   BEGIN
    PRINT 'Neither Country nor Region was passed in.'
   END -- end inner if
  END -- end outer if
 -- other statements
 END

答案 5 :(得分:0)

我会使用公用表表达式