将 if/else 转换为大小写

convert if/else to case

我想知道是否有人能够并愿意帮助我。 在我的 Sql 服务器存储过程中,我有一系列 if / else if 语句,我需要一些帮助将其更改为 case...when...then,因为我觉得它会更有效率并且看起来少凌乱。 我并不是要你为我做这件事,只是一个简单的例子,让我能够理解它。

我的存储过程如下...

CREATE PROCEDURE [Blog].[ttc_BlogPosts]
@Status varchar(50) = '' ,
@EntryId int = '',
@Title nvarchar(max) = '',
@Added datetime = '',
@Updated datetime = '',
@Message nvarchar(max) = '',
@ImgId int = '',
@ImgUrl nvarchar(max) = ''

AS
BEGIN
     IF(@Status = 'Display')
       begin
            select Id, EntryTitle, Message, ImageUrl, DateAdded, LastEdited
            from Blog.BlogEntry
            order by DateAdded desc
       end

     else if(@Status = 'AddPost')
            begin

                insert into Blog.BlogEntry (EntryTitle, Message, DateAdded, ImageUrl)
                values (@Title, @Message, GETDATE(), @ImgUrl)   
            end
          else if(@Status = 'DisplayPost')
                 begin
                      select EntryTitle, DateAdded, LastEdited, Message, ImageUrl
                      from Blog.BlogEntry
                      where Id = @EntryId
                  end
               else if(@Status = 'UpdatePost')
                      begin
                          update Blog.BlogEntry
                          set EntryTitle = @Title, Message = @Message, LastEdited = GETDATE()
                          where Id = @EntryId
                      end 
                    else if(@Status = 'UpdatePostImage')
                           begin
                           update Blog.BlogEntry
                           set ImageUrl = @ImgUrl, LastEdited = GETDATE(), EntryTitle = @Title, Message = @Message
                           where Id = @EntryId
                        end
                     else if(@Status = 'DeletePost')
                         begin
                              delete from Blog.BlogEntry
                              where Id = @EntryId 
                          end
          END

非常感谢你们愿意提供的任何帮助。如果需要任何进一步的详细信息,请随时告诉我 ;)

担心你的代码看起来如何,我会更担心这段代码的执行方式,你会在这个过程中遇到巨大的参数嗅探问题,为了避免它你需要动态 sql 这样sql 服务器可以缓存此过程的参数化执行计划,而不是拥有一个执行计划并尝试使用相同的计划执行每个查询。

您还有一些变量值设置为无效值,例如 Int 变量被设置为空字符串 '' 日期时间变量也被设置为空字符串,请看下面,此过程应该可以帮助您更好的性能。

CREATE PROCEDURE [Blog].[ttc_BlogPosts]
    @Status     varchar(50)   = '' ,
    @EntryId    int           = NULL,  --< can't set int variable to empty string
    @Title      nvarchar(max) = '',
    @Added      datetime      = NULL,    --< can't set Date/DateTime variable to empty string
    @Updated    datetime      = NULL,
    @Message    nvarchar(max) = '',
    @ImgId      int           = NULL,
    @ImgUrl     nvarchar(max) = ''
AS
BEGIN
  SET NOCOUNT ON;

  DECLARE @Sql NVARCHAR(MAX);

-- A validate check since your else..if statement don't handle this case
IF (@Status = '')
 BEGIN
  RAISERROR('Provide value for @Status variable',16,1)
  RETURN
 END

    IF(@Status = 'Display')
        begin
            SET @Sql = N'
            select Id, EntryTitle, Message, ImageUrl, DateAdded, LastEdited
            from Blog.BlogEntry
            order by DateAdded desc'
        end
    else if(@Status = 'AddPost')
        begin
            SET @Sql = N'
            insert into Blog.BlogEntry (EntryTitle, Message, DateAdded, ImageUrl)
            values (@Title, @Message, GETDATE(), @ImgUrl)'   
        end
    else if(@Status = 'DisplayPost')
        begin
            SET @Sql = N'
            select EntryTitle, DateAdded, LastEdited, Message, ImageUrl
            from Blog.BlogEntry
            where Id = @EntryId'
        end
    else if(@Status = 'UpdatePost')
        begin
            SET @Sql = N'
            update Blog.BlogEntry
            set EntryTitle = @Title, Message = @Message, LastEdited = GETDATE()
            where Id = @EntryId'
        end 
    else if(@Status = 'UpdatePostImage')
        begin
            SET @Sql = N'
            update Blog.BlogEntry
            set ImageUrl = @ImgUrl, LastEdited = GETDATE(), EntryTitle = @Title, Message = @Message
            where Id = @EntryId'
        end
    else if(@Status = 'DeletePost')
        begin
            SET @Sql = N'
            delete from Blog.BlogEntry
            where Id = @EntryId'
        end

Exec sp_executesql @Sql 
                  ,N'@Status varchar(50),@EntryId int, @Title nvarchar(max), @Added datetime, 
                    @Updated datetime, @Message nvarchar(max), @ImgId int, @ImgUrl nvarchar(max)'
                  ,@Status 
                  ,@EntryId 
                  ,@Title 
                  ,@Added
                  ,@Updated 
                  ,@Message 
                  ,@ImgId 
                  ,@ImgUrl 
END

因此,本着

的精神

"just a quick example to enable me to get my head around it..."

你可以做动态 SQL.

DECLARE @SQL VARCHAR(MAX)

SELECT @SQL = CASE
                  WHEN @Status = 'Display' THEN @SQL = 'select Id, EntryTitle, Message, ImageUrl, DateAdded, LastEdited from Blog.BlogEntry    order by DateAdded desc'
                  WHEN @Status = 'DisplayPost' THEN ...
                  WHEN @Status = 'UpdatePost' THEN ...
                  WHEN @Status = 'UpdatePostImage' THEN ...
                  WHEN @Status = 'DeletePost' THEN ...
              END

EXEC (@SQL)

您要 运行 的唯一问题是您需要将变量连接到您的语句中,如下所示

THEN @SQL = 'update Blog.BlogEntry set EntryTitle =''' + @Title + ''', Message =''' + @Message + ''', LastEdited = ''' + GETDATE() + ''' where Id = ''' @EntryId

在SQL中,IF/ELSE与CASE/WHEN的功能完全不同,两者很少可以互换。

IF/ELSE可用于控制流量:

IF This
  DO THAT
ELSE
  DO Something else

CASE/WHEN returns单个值,无法控制流量

SET @MyValue = CASE 
  WHEN [Color] = 'Red' THEN 1
  ELSE 0
END

您的代码不适合 CASE/WHEN,因为您使用 IF/ELSE 来控制流程。

这会奏效。这是 IF .. ELSE 到 CASE.. ELSE ... END

的简单转换
CREATE PROCEDURE [Blog].[ttc_BlogPosts]
@Status varchar(50) = '' ,
@EntryId int = '',
@Title nvarchar(max) = '',
@Added datetime = '',
@Updated datetime = '',
@Message nvarchar(max) = '',
@ImgId int = '',
@ImgUrl nvarchar(max) = ''

AS
BEGIN
     CASE WHEN(@Status = 'Display')
        THEN
            select Id, EntryTitle, Message, ImageUrl, DateAdded, LastEdited
            from Blog.BlogEntry
            order by DateAdded desc


        ELSE (CASE WHEN(@Status = 'AddPost')
              THEN

                insert into Blog.BlogEntry (EntryTitle, Message, DateAdded, ImageUrl)
                values (@Title, @Message, GETDATE(), @ImgUrl)   

              ELSE (CASE WHEN(@Status = 'DisplayPost')
                     THEN
                          select EntryTitle, DateAdded, LastEdited, Message, ImageUrl
                          from Blog.BlogEntry
                          where Id = @EntryId

                   ELSE (CASE WHEN(@Status = 'UpdatePost')
                          THEN
                              update Blog.BlogEntry
                              set EntryTitle = @Title, Message = @Message, LastEdited = GETDATE()
                              where Id = @EntryId

                        ELSE (CASE WHEN(@Status = 'UpdatePostImage')
                               THEN
                               update Blog.BlogEntry
                               set ImageUrl = @ImgUrl, LastEdited = GETDATE(), EntryTitle = @Title, Message = @Message
                               where Id = @EntryId

                               ELSE (CASE WHEN(@Status = 'DeletePost')
                                 THEN
                                      delete from Blog.BlogEntry
                                      where Id = @EntryId 
                                  END)
                               END)
                         END)
                     END)
                END)
            END
END

使用 解决方案与搜索 CASE 比较可读性问题。

还添加了额外的@status 验证

CREATE PROCEDURE [Blog].[ttc_BlogPosts]
     @Status     varchar(50)   = '' ,
     @EntryId    int           = NULL,  
     @Title      nvarchar(max) = '',
     @Added      datetime      = NULL,    
     @Updated    datetime      = NULL,
     @Message    nvarchar(max) = '',
     @ImgId      int           = NULL,
     @ImgUrl     nvarchar(max) = ''
 AS
 BEGIN
 SET NOCOUNT ON;

 DECLARE @Sql NVARCHAR(MAX);

-- A validate check since your else..if statement don't handle this case
IF (@Status = '' AND @Status NOT IN ('Display', 'DisplayPost', ...))
BEGIN
   RAISERROR('Provide value for @Status variable. Allowed values (Display, ...)',16,1)
   RETURN
END

SELECT @sql = CASE @status 
    WHEN 'Display' THEN
        N'select Id, EntryTitle, Message, ImageUrl, DateAdded, LastEdited
        from Blog.BlogEntry
        order by DateAdded desc'

    WHEN 'AddPost' THEN
        N'insert into Blog.BlogEntry (EntryTitle, Message, DateAdded, ImageUrl)
        values (@Title, @Message, GETDATE(), @ImgUrl)'   

    WHEN 'DisplayPost' THEN
        N'select EntryTitle, DateAdded, LastEdited, Message, ImageUrl
        from Blog.BlogEntry
        where Id = @EntryId'

    WHEN 'UpdatePost' THEN
        N'update Blog.BlogEntry
        set EntryTitle = @Title, Message = @Message, LastEdited = GETDATE()
        where Id = @EntryId'

    WHEN 'UpdatePostImage' THEN
        N'update Blog.BlogEntry
        set ImageUrl = @ImgUrl, LastEdited = GETDATE(), EntryTitle = @Title, Message = @Message
        where Id = @EntryId'

    WHEN 'DeletePost' THEN
        N'delete from Blog.BlogEntry
        where Id = @EntryId'
   END

EXEC [dbo].[sp_executesql] @Sql 
              ,N'@Status varchar(50),@EntryId int, @Title nvarchar(max), @Added datetime, 
                @Updated datetime, @Message nvarchar(max), @ImgId int, @ImgUrl nvarchar(max)'
              ,@Status 
              ,@EntryId 
              ,@Title 
              ,@Added
              ,@Updated 
              ,@Message 
              ,@ImgId 
              ,@ImgUrl 
END