SQL,如何使用动态条件逻辑?
当您需要动态WHERE子句时,我可以使用SQL,如何使用动态条件逻辑?,sql,sql-server,dynamic,conditional-statements,Sql,Sql Server,Dynamic,Conditional Statements,当您需要动态WHERE子句时,我可以使用 CREATE PROCEDURE [dbo].[sp_sel_Articles] @articleId INT = NULL , @title NVARCHAR(250) = NULL , @accessLevelId INT = NULL AS BEGIN SELECT * FROM table_A
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或小于
当前程序只能使用处理精确的值
Art.AccessLevelId = @accessLevelId
是否也可以将条件类型以及值输入到程序中?在这个例子中可能看起来很奇怪,但请耐心听我说:
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条件
提前感谢,您可能需要使用动态SQL来传递操作符。或者您可以传入两个值,例如
@MinAccessLevelID INT,
@MaxAccessLevelID INT
...
WHERE (
(@MinAccessLevelID IS NULL AND @MaxAccessLevelID IS NULL)
OR
(AccessLevelID >= @MinAccessLevelID AND AccessLevelID <= @MaxAccessLevelID)
)
@MinAccessLevelID INT,
@MaxAccessLevelID INT
...
在哪里(
(@MinAccessLevelID为NULL,@MaxAccessLevelID为NULL)
或
(AccessLevelID>=@MinAccessLevelID和AccessLevelID只要创建一个查询字符串,就可以随时进行动态查询
execute ('select count(*) from table' )
因此,通过在存储过程中输入的参数,您还可以形成一个查询字符串,您可以执行该字符串。在应用之前,请阅读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
您可以使用case语句-如果格式不正确,它可能看起来有点滑稽,但您可以尝试以下操作:
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
从SomeTable中选择列
其中1=案例
当@SomeOption=''和SomeValue>=@SomeMinParam和SomeValue不调用您的SPs时,我认为这不会得到您期望的结果,原因有两个:(1)应该产生<,而不是=(2)SomeValue不能同时是>@SomeParam
和<@SomeParam
。我对它进行了更新,以添加缺少的max-param-我认为,尽管您可以使用NULL来指定max仅使用Min,但它使它更易于阅读,而无需查看存储过程的定义(然后,您可能需要再次打开它以查看可能的参数值)-也许命名参数“@accessLevelMustEqualMin”并使其更清晰一点?我可能会像Aaron那样使用NULL,老实说:)我说的是您的第一个代码段。我的评论是在您添加过程之前发布的。谢谢。这是我第一次想到的。但是对于所有过程的每个字段都可能有=、=、<或>。我试图避免使用这种方法,但毕竟我可能不得不使用这种方法。Aarons可能会更有用,因为看起来更合乎逻辑的是——你通过两个相同的值来获得一个项目。我想这取决于你对什么感到满意——但别忘了对必须维护它的可怜的草皮进行评论:有人不喜欢动态SQL,否则我不清楚反对票。正如OP所说,他可能有>=,>,=,
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