我有一个返回数据的存储过程。
我需要根据传入的参数更改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?
由于
答案 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)
我会使用公用表表达式