Using CASE to create SQL Statement

  • In a Stored Proc, can you use a CASE statement to create your SQL ... (the below try errors out on 'Case'

    ALTER procedure [dbo].[test]

    @model varchar(1000),

    @from1 varchar(1000),

    @from2 varchar(1000),

    @from3 varchar(1000)

    AS

    declare

    @Cmd varchar(1000),

    ------------------------------------------------------------------------------------- Begin Procedure ---------------------------------------------------------------|

    begin

    case

    when @model = 'Global' then

    Set @Cmd ='

    SELECT '+@model+' AS Model

    , Scenario_ID

    FROM lp_Scenario AS a

    Else

    SET @Cmd = '

    SELECT '+@model+' AS Model

    , a.Scenario_ID

    , a.Last_Gen_DT

    FROM '+@from1+' a

    INNER JOIN '+@from2+' b

    ON a.User_ID = b.User_ID

    WHERE (a.Scenario_ID =

    (SELECT Scenario_ID

    FROM '+@from3+' AS z

    WHERE (Auto_Update = 1)))'

    End

    GO

    EXEC (@Cmd)

  • No that is not how case works in sql. You need to use an IF - ELSE construct.

    And You should read up on sql injection. Your procedure is wide open.

    _______________________________________________________________

    Need help? Help us help you.

    Read the article at http://www.sqlservercentral.com/articles/Best+Practices/61537/ for best practices on asking questions.

    Need to split a string? Try Jeff Modens splitter http://www.sqlservercentral.com/articles/Tally+Table/72993/.

    Cross Tabs and Pivots, Part 1 – Converting Rows to Columns - http://www.sqlservercentral.com/articles/T-SQL/63681/
    Cross Tabs and Pivots, Part 2 - Dynamic Cross Tabs - http://www.sqlservercentral.com/articles/Crosstab/65048/
    Understanding and Using APPLY (Part 1) - http://www.sqlservercentral.com/articles/APPLY/69953/
    Understanding and Using APPLY (Part 2) - http://www.sqlservercentral.com/articles/APPLY/69954/

  • That is a simplistic version of the code.. the problem I have with IF statements, is that you have to create a very long IF THEN Else IF... version to deal with all the possible Model's in this case... and it makes reading the code a lot harder. If I have to go that route then I will just create a stored proc for each set of models that use the same select statements.

  • I figured it was a stripped down version but yes you have to use if type logic for this. CASE is not used as a control block like a switch statement in c#.

    Regardless of which approach you take you seriously need to look at sql injection. The code posted is extremely vulnerable.

    _______________________________________________________________

    Need help? Help us help you.

    Read the article at http://www.sqlservercentral.com/articles/Best+Practices/61537/ for best practices on asking questions.

    Need to split a string? Try Jeff Modens splitter http://www.sqlservercentral.com/articles/Tally+Table/72993/.

    Cross Tabs and Pivots, Part 1 – Converting Rows to Columns - http://www.sqlservercentral.com/articles/T-SQL/63681/
    Cross Tabs and Pivots, Part 2 - Dynamic Cross Tabs - http://www.sqlservercentral.com/articles/Crosstab/65048/
    Understanding and Using APPLY (Part 1) - http://www.sqlservercentral.com/articles/APPLY/69953/
    Understanding and Using APPLY (Part 2) - http://www.sqlservercentral.com/articles/APPLY/69954/

  • dwilliscp (6/27/2012)


    In a Stored Proc, can you use a CASE statement to create your SQL ... (the below try errors out on 'Case'

    ALTER procedure [dbo].[test]

    @model varchar(1000),

    @from1 varchar(1000),

    @from2 varchar(1000),

    @from3 varchar(1000)

    AS

    declare

    @Cmd varchar(1000),

    ------------------------------------------------------------------------------------- Begin Procedure ---------------------------------------------------------------|

    begin

    case

    when @model = 'Global' then

    Set @Cmd ='

    SELECT '+@model+' AS Model

    , Scenario_ID

    FROM lp_Scenario AS a

    Else

    SET @Cmd = '

    SELECT '+@model+' AS Model

    , a.Scenario_ID

    , a.Last_Gen_DT

    FROM '+@from1+' a

    INNER JOIN '+@from2+' b

    ON a.User_ID = b.User_ID

    WHERE (a.Scenario_ID =

    (SELECT Scenario_ID

    FROM '+@from3+' AS z

    WHERE (Auto_Update = 1)))'

    End

    GO

    EXEC (@Cmd)

    Very Good and critical point raised by Sean for this piece of code.SQL injection is very much possible here.Don't let user to run their query by your vulnerable code.It can harm you and your company both.

    The CASE expression cannot be used to control the flow of execution of Transact-SQL statements, statement blocks, user-defined functions, and stored procedures.

    --rhythmk
    ------------------------------------------------------------------
    To post your question use below link

    https://www.sqlservercentral.com/articles/forum-etiquette-how-to-post-datacode-on-a-forum-to-get-the-best-help
    πŸ™‚

  • I created that set of code, for this example to show what I was trying to do.. not the code that is in the stored proc (it is doing a lot more that this simple creation does).. my point was just to show what I wanted to do... and that was to use the case statement to create the SQL statement depending on the Model being passed into the code. In fact the Stored Proc can only be run by the Admin, and is used to load data during nightly processing.

  • dwilliscp (6/27/2012)


    That is a simplistic version of the code.. the problem I have with IF statements, is that you have to create a very long IF THEN Else IF... version to deal with all the possible Model's in this case... and it makes reading the code a lot harder. If I have to go that route then I will just create a stored proc for each set of models that use the same select statements.

    The version using IF looks nearly identical to me.

    --case when

    IF @model = 'Global' -- then

    Set @Cmd ='

    SELECT '+@model+' AS Model

    , Scenario_ID

    FROM lp_Scenario AS a'

    -- Second THEN of CASE

    -- ELSE IF @model = 'Something' -- Uses ELSE IF instead of WHEN/THEN

    -- Then

    Else

    SET @Cmd = '

    SELECT '+@model+' AS Model

    , a.Scenario_ID

    , a.Last_Gen_DT

    FROM '+@from1+' a

    INNER JOIN '+@from2+' b

    ON a.User_ID = b.User_ID

    WHERE (a.Scenario_ID =

    (SELECT Scenario_ID

    FROM '+@from3+' AS z

    WHERE (Auto_Update = 1)))'

    --End


    My mantra: No loops! No CURSORs! No RBAR! Hoo-uh![/I]

    My thought question: Have you ever been told that your query runs too fast?

    My advice:
    INDEXing a poor-performing query is like putting sugar on cat food. Yeah, it probably tastes better but are you sure you want to eat it?
    The path of least resistance can be a slippery slope. Take care that fixing your fixes of fixes doesn't snowball and end up costing you more than fixing the root cause would have in the first place.

    Need to UNPIVOT? Why not CROSS APPLY VALUES instead?[/url]
    Since random numbers are too important to be left to chance, let's generate some![/url]
    Learn to understand recursive CTEs by example.[/url]
    [url url=http://www.sqlservercentral.com/articles/St

  • But if you're wedded to CASE you can do it like this:

    SELECT @CMD=

    case

    when @model = 'Global' then

    'SELECT '+@model+' AS Model

    , Scenario_ID

    FROM lp_Scenario AS a'

    Else

    'SELECT '+@model+' AS Model

    , a.Scenario_ID

    , a.Last_Gen_DT

    FROM '+@from1+' a

    INNER JOIN '+@from2+' b

    ON a.User_ID = b.User_ID

    WHERE (a.Scenario_ID =

    (SELECT Scenario_ID

    FROM '+@from3+' AS z

    WHERE (Auto_Update = 1)))'

    End

    SELECT @CMD


    My mantra: No loops! No CURSORs! No RBAR! Hoo-uh![/I]

    My thought question: Have you ever been told that your query runs too fast?

    My advice:
    INDEXing a poor-performing query is like putting sugar on cat food. Yeah, it probably tastes better but are you sure you want to eat it?
    The path of least resistance can be a slippery slope. Take care that fixing your fixes of fixes doesn't snowball and end up costing you more than fixing the root cause would have in the first place.

    Need to UNPIVOT? Why not CROSS APPLY VALUES instead?[/url]
    Since random numbers are too important to be left to chance, let's generate some![/url]
    Learn to understand recursive CTEs by example.[/url]
    [url url=http://www.sqlservercentral.com/articles/St

  • dwain.c (6/27/2012)


    But if you're wedded to CASE you can do it like this:

    SELECT @CMD=

    case

    when @model = 'Global' then

    'SELECT '+@model+' AS Model

    , Scenario_ID

    FROM lp_Scenario AS a'

    Else

    'SELECT '+@model+' AS Model

    , a.Scenario_ID

    , a.Last_Gen_DT

    FROM '+@from1+' a

    INNER JOIN '+@from2+' b

    ON a.User_ID = b.User_ID

    WHERE (a.Scenario_ID =

    (SELECT Scenario_ID

    FROM '+@from3+' AS z

    WHERE (Auto_Update = 1)))'

    End

    SELECT @CMD

    Hey Dwain,

    Finally you make dwilliscp's day πŸ˜‰

    --rhythmk
    ------------------------------------------------------------------
    To post your question use below link

    https://www.sqlservercentral.com/articles/forum-etiquette-how-to-post-datacode-on-a-forum-to-get-the-best-help
    πŸ™‚

  • Finally? I didn't realize I was on a deadline...:w00t:


    My mantra: No loops! No CURSORs! No RBAR! Hoo-uh![/I]

    My thought question: Have you ever been told that your query runs too fast?

    My advice:
    INDEXing a poor-performing query is like putting sugar on cat food. Yeah, it probably tastes better but are you sure you want to eat it?
    The path of least resistance can be a slippery slope. Take care that fixing your fixes of fixes doesn't snowball and end up costing you more than fixing the root cause would have in the first place.

    Need to UNPIVOT? Why not CROSS APPLY VALUES instead?[/url]
    Since random numbers are too important to be left to chance, let's generate some![/url]
    Learn to understand recursive CTEs by example.[/url]
    [url url=http://www.sqlservercentral.com/articles/St

  • Hey all, have a look at these two articles.

    http://www.sqlservercentral.com/articles/Performance+Tuning/howdynamiccanstaticbe/631/

    and http://www.sqlservercentral.com/articles/Performance+Tuning/howdynamicsqlcanbestatic2/684/

    An nice fancy way of building SQL using case statements and it covers select, where, joins and other niceties. Of course it won't perform well as plan generation is difficult but the concept is nice and fancy.

  • .... No loops! No CURSORs! No RBAR! Hoo-uh! ...

    Great!

    Thanks rhythmk and dwain.c for your help...

    The IF statement would have 5 nested IF's... and then the else.. I know it is just my preference.. but if you can not get it done in a If Then Else.. then I like to use Case. Doing less C coding in this new position and a lot more SQL... no Pick though, so I guess it is a good trade off. :hehe:

    Again thanks for your help!

  • I headed out for vacation last week, only to end up with no power... after the big storm moved through the Smokey Mountains Friday... so I am back early πŸ™

  • You will find far better performance and code maintenance by creating a sproc for each of your different select statements. The code dwain posted is indeed quite a clever way of making case somewhat function like a programming block. The downside is the performance of that is going to suffer greatly and tracking it down will become painful. Not to mention that code will be a lot harder to maintain because dynamic sql is just harder to read when it gets complicated like that. Just my 2Β’.

    _______________________________________________________________

    Need help? Help us help you.

    Read the article at http://www.sqlservercentral.com/articles/Best+Practices/61537/ for best practices on asking questions.

    Need to split a string? Try Jeff Modens splitter http://www.sqlservercentral.com/articles/Tally+Table/72993/.

    Cross Tabs and Pivots, Part 1 – Converting Rows to Columns - http://www.sqlservercentral.com/articles/T-SQL/63681/
    Cross Tabs and Pivots, Part 2 - Dynamic Cross Tabs - http://www.sqlservercentral.com/articles/Crosstab/65048/
    Understanding and Using APPLY (Part 1) - http://www.sqlservercentral.com/articles/APPLY/69953/
    Understanding and Using APPLY (Part 2) - http://www.sqlservercentral.com/articles/APPLY/69954/

  • Sean Lange (7/2/2012)


    You will find far better performance and code maintenance by creating a sproc for each of your different select statements. The code dwain posted is indeed quite a clever way of making case somewhat function like a programming block. The downside is the performance of that is going to suffer greatly and tracking it down will become painful. Not to mention that code will be a lot harder to maintain because dynamic sql is just harder to read when it gets complicated like that. Just my 2Β’.

    Are you sure, Sean? I totally agree with debugging and maintenance being a pain in the a$$ but I'm not so sure about performance.

    β€œWrite the query the simplest way. If through testing it becomes clear that the performance is inadequate, consider alternative query forms.” - Gail Shaw

    For fast, accurate and documented assistance in answering your questions, please read this article.
    Understanding and using APPLY, (I) and (II) Paul White
    Hidden RBAR: Triangular Joins / The "Numbers" or "Tally" Table: What it is and how it replaces a loop Jeff Moden

Viewing 15 posts - 1 through 15 (of 17 total)

You must be logged in to reply to this topic. Login to reply