Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
SQL,如何使用动态条件逻辑?_Sql_Sql Server_Dynamic_Conditional Statements - Fatal编程技术网

SQL,如何使用动态条件逻辑?

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

当您需要动态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或小于

当前程序只能使用处理精确的

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