2015-08-24 71 views
0

我想知道有沒有人能夠並願意協助我。 在我的Sql Server存儲過程中,我有一系列的if/else if語句,我希望有一點幫助可以將它更改爲case ... when ...然後,因爲我覺得它會更有效率,看起來不那麼混亂。 我不是要求你爲我做這件事,只是一個簡單的例子,讓我能夠把握住它。將if/else轉換爲case

我strored過程如下...

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 

任何幫助,你們願意提供將非常感謝。如果需要進一步的細節,請不要猶豫給我留言;)

+0

一件事,你現在可以做的就是添加縮進開始結束塊這將是更具可讀性。 – lad2025

+0

簡單答案[案件不是用於控制流(https://msdn.microsoft.com/en-us/library/ms174290.aspx) – lad2025

+0

我認爲這是一種有效的代碼,因爲它僅要求每個指定一個SP行動。但是,如果您對此腳本感到厭煩,那麼僅僅因爲它不是面向事務的,就知道每個存儲過程腳本中的BEGIN TRAN - DO HERE - END TRAN。 :) –

回答

1

使用M.Ali解決方案與CASE搜索比較可讀性的關注。

還添加addtional @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 
+0

堅持以提高可讀性,ID投給這個「案例」,即使它仍然看起來像一個IF語句和exec @statement作爲一個安樂窩;) –

+0

只是一個快速的一個,我得到了以下警告:警告 SQL71502:過程:[Blog]。[ttc_BlogPosts]包含對對象的未解析引用。對象不存在或引用不明確,因爲它可能引用以下任何對象:[Blog]。[sp_executesql]或[dbo]。[sp_executesql]我輸入了錯誤的東西嗎?恐怕我不確定哪個是正確的?添加我正在與之交互的模式?即博客 –

+0

@M_Griffiths什麼警告? – lad2025

1

擔心你的代碼看起來如何,我會更擔心這個代碼將如何執行,你會得到巨大的參數嗅探問題這個過程,爲了避免它,你需要動態的sql,這樣sql server就可以爲這個過程緩存一個參數化的執行PLANS,而不是有一個執行計劃,並試圖使用相同的計劃執行每個查詢。

此外,你有一些變量值設置爲無效的值,如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 
+0

你可以用'SELECT @sql = CASE @Status WHEN'顯示'...'來產生這個@sql,這將是一個更清晰的方式。 – lad2025

+0

@ lad2025由於可讀性也是一個問題,因此在CASE語句中添加大量代碼行會使其閱讀起來非常困難。當您只處理可選參數時,CASE語句是很好的。只是有一天,我在這裏使用case語句都看['可選Parameters'(http://dba.stackexchange.com/questions/108903/dynamic-filters-in-sql-server/108908#108908) –

+0

所以給了一個答案只需將他的解決方案封裝到Dynamic SQL中,使其不易讀。 – lad2025

0

所以,在

本着「只是一個簡單的例子,使我能夠得到我的頭周圍......」

你可以做動態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 
+1

偉大的答案,打開他SQL注入。 – lad2025

0

在SQL中的if/else提供完全不同的功能來自CASE/WHEN,而且兩者很少可以互換。

IF/ELSE可用於控制流量:

IF This 
    DO THAT 
ELSE 
    DO Something else 

CASE/WHEN返回單個值,且無法控制流動。

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

你的代碼是不是CASE一個很好的候選人/ WHEN,因爲你正在使用的if/else控制流。

0

這將工作。這是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 
相關問題