当您需要动态WHERE条款时,我可以使用;
CREATE PROCEDURE [dbo].[sp_sel_Articles]
@articleId INT = NULL
, @title NVARCHAR(250) = NULL
, @accessLevelId INT = NULL
AS
BEGIN
SELECT *
FROM table_Articles Art
WHERE
(Art.ArticleId = @articleId OR @articleId IS NULL)
AND (Art.Title LIKE '%' + @title + '%' OR @title IS NULL)
AND (Art.AccessLevelId = @accessLevelId OR @accessLevelId IS NULL)
END
所以,我可以通过ArticleId调用此程序 - 例如仅
EXEC [sp_sel_Articles] @articleId = 3
但是,有时我需要通过AccessLevelId调用,有时不是通过精确值调用。例如,我需要比给定的accesslevelId更多或更少。
当前程序可以仅使用
处理 EXACT 值Art.AccessLevelId = @accessLevelId
还可以将 CONDITION 类型以及值添加到过程中吗?在这个例子中看起来很奇怪,但请跟我一起承担:
CREATE PROCEDURE [dbo].[sp_sel_Articles]
@articleId INT = NULL
, @title NVARCHAR(250) = NULL
, @accessLevelId INT = NULL
, **@accessLevelIdCondition**
AS
BEGIN
SELECT *
FROM table_Articles Art
WHERE
(Art.ArticleId = @articleId OR @articleId IS NULL)
AND (Art.Title LIKE '%' + @title + '%' OR @title IS NULL)
AND (Art.AccessLevelId **@accessLevelIdCondition** @accessLevelId OR @accessLevelId IS NULL)
END
也许可以使用一个功能,我不知道。因为,至少有20个程序需要这种灵活性,我需要尽可能多地采用更全面的解决方案,而不是在每个程序中编写IF ELSE条件。
提前致谢,
答案 0 :(得分:3)
您可能需要使用动态SQL传递运算符。或者你可以传入两个值,例如
@MinAccessLevelID INT,
@MaxAccessLevelID INT
...
WHERE (
(@MinAccessLevelID IS NULL AND @MaxAccessLevelID IS NULL)
OR
(AccessLevelID >= @MinAccessLevelID AND AccessLevelID <= @MaxAccessLevelID)
)
当你想要精确(例如只有3)时,只需将3传递给两个值。当你想要任何高于3的东西时,将20000000000传递给@Max参数,如果你想要低于3的所有东西,则传递0。
但是你会发现,随着这些排列变得越来越复杂,你最好只使用动态SQL(并设置optimize for ad hoc workloads
,这对于计划缓存重用和阻止参数嗅探更好)。
答案 1 :(得分:2)
在申请之前阅读此www.sommarskog.se/dynamic_sql.html
CREATE PROCEDURE [dbo].[sp_sel_Articles]
@articleId INT = NULL
, @title NVARCHAR(250) = NULL
, @accessLevelId INT = NULL
, @accessLevelIdCondition varchar(100)
AS
BEGIN
DECLARE @SQL varchar(8000)
SET @SQL='
SELECT *
FROM table_Articles Art
WHERE
(Art.ArticleId = '+cast(@articleId as varchar(100))+' OR '+cast(@articleId as varchar(100))+'IS NULL)
AND (Art.Title LIKE ''%'' + @title + ''%'' OR @title IS NULL)
AND (Art.AccessLevelId '+@accessLevelIdCondition+ cast(@accessLevelId as varchar(100))+' OR '+cast(@accessLevelId as varchar(100))+' IS NULL) '
EXEC(@sql)
END
答案 2 :(得分:1)
您只需制作查询字符串即可创建动态查询
execute ('select count(*) from table' )
因此,通过在存储过程中输入的参数,您还可以形成一个可以执行的查询字符串。
答案 3 :(得分:1)
您可以使用案例陈述 - 如果格式不正确,它看起来会有点滑稽,但您可以尝试以下内容:
SELECT Columns FROM SomeTable
WHERE 1 = CASE
WHEN @SomeOption = '<>' AND SomeValue >= @SomeMinParam AND SomeValue <= SomeMaxParam THEN 1
WHEN @SomeOption '=' AND SomeValue = @SomeMinParam THEN 1
ELSE 0
END
(尽管Aaron指出 - 你传入的&lt;&gt;并没有真正反映声明中的比较运算符 - 将其更改为有意义的东西:))
在你的情况下:
CREATE PROCEDURE [dbo].[sp_sel_Articles]
@articleId INT = NULL,
@title NVARCHAR(250) = NULL,
@MinaccessLevelId INT = NULL,
@MaxaccessLevelId INT = NULL,
@accessType varchar(5) = '<>'
AS
BEGIN
SELECT *
FROM table_Articles Art
WHERE
(Art.ArticleId = @articleId OR @articleId IS NULL)
AND (Art.Title LIKE '%' + @title + '%' OR @title IS NULL)
AND 1 = CASE
WHEN @accessType = '<>' AND (Art.AccessLevelId = @MinaccessLevelId OR @accessLevelId IS NULL) THEN 1
WHEN @accessType = '=' AND (Art.AccessLevelId >= @MinaccessLevelId OR Art.AccessLevelId <= @MaxaccessLevelId) THEN 1
ELSE 0
END
END
对于@accessType参数,可能使用@CompareAccessLevelToMin而不是varchar()。仍然有一个麻烦,就是不要告诉你,将它设置为“假”意味着什么。