Skip to Main Content

Breadcrumb

Question and Answer

Chris Saxon

Thanks for the question, Vannessa.

Asked: April 25, 2017 - 2:21 pm UTC

Last updated: March 19, 2020 - 5:16 pm UTC

Version: Oracle 11 g express edition

Viewed 10K+ times! This question is

You Asked

hello,
i have wrote normally a long query and i use many case statements and i want to reuse this query. therefore i want to create a procedure with parameter to do that. At the end i want to create a view or a table with this query. therefore i have to use dynamic sql.

The parameter of the procedure is the column name that i want to used in the case statement. That means i don't want to write it hard coded.
i tried with bind variables and using concatenate but that seems not really to work.
Therefore i want to know if it is possible to do that. i have read that identifiers are not allowed as bind variables. But if it is feasible , is there a way to create a view from the resultset of this procedure?

thanks for the answer.


with LiveSQL Test Case:

and Chris said...

I really don't understand why you think you need dynamic SQL here. Creating views on-the-fly this way is a bad idea.

Why can't you place the case expression in a regular query, like so:

create Table Test( 
amount Number (7,3), 
price Number(7,3));

insert into Test Values (1,30);
insert into test values (2,40);

select t.*,
       case when amount = 1 then price / amount END as price2
from   test t;

AMOUNT  PRICE  PRICE2  
1       30     30      
2       40 

create or replace view v as 
  select t.*,
         case when amount = 1 then price / amount END as price2
  from   test t;

select * from v;

AMOUNT  PRICE  PRICE2  
1       30     30      
2       40  

Rating

  (4 ratings)

Is this answer out of date? If it is, please let us know via a Comment

Comments

Vannessa Kabiwo, April 26, 2017 - 7:43 am UTC

i need dynamic SQL because this long sql that i have wrote, has to be reuse by a team, that has no idea about this. for simplifying that, i want to add this long sql in a procedure and then the member of the team has just to call this procedure to execute this query.
Chris Saxon
April 27, 2017 - 9:29 am UTC

That doesn't explain why you need dynamic SQL. Static SQL in a procedure does the same job!

Did not seem to understand the question

Badlands, May 24, 2019 - 3:02 am UTC

I am facing a similar situation which I think the original poster was inquiring about. In my situation, I have a 200 column staging table. One hundred of those columns represent a score and the other 100 columns are correlated dates to each score.

I successfully used UNPIVOT to turn the 100 score columns into 100 rows which was the main goal. But now I'm struggling to pick up the value of the related score date column for that score.

It seems that a case statement is the solution:

CASE colm -- colm is used in UNPIVOT to capture column name
WHEN 'score_column_1' THEN date_column_1
WHEN 'score_column_2' THEN date_column_2

But I prefer not to have 100 when statements if possible. So far, the best I can do is to get the CASE statement to return the name of the date column, but I really want the value.

I believe that the original poster was facing a similar scenario. If colm = 'score_column_1' then I can manipulate that string to turn into 'date_column_1', but I don't want that string I want the value of date_column_1.

This probably looks ridiculous, but it may help further explain what I an I believe the original poster are trying to accomplish. I tried the following to get the date value to be return with its related score:

WHEN colm IN ('X','Y','Z') THEN EXECUTE IMMEDIATE 'BEGIN :1 := '||colm||'_DATE; END;' USING OUT N
END

For example, if the score column was 'X', then the UNPIVOT is giving me both the column name of 'X' and the column value of say 89. Now I know that I want the value from the X_DATE column in the 200 column staging table, but it does not seem possible in a case statement.

Any thoughts would be appreciated.
Chris Saxon
May 24, 2019 - 8:39 am UTC

While similar, I'm not sure this is exactly what the OP was asking about...

From what I understand of your issue my point still stands though: you don't need dynamic SQL. You just want to use it to save some typing!

Personally I think the risks of dynamic SQL (namely - SQL injection) mean you should stick with the statically typed case statements. As a rule improved security comes at the cost of usability. In this case programmer convenience.

Of course, if I am missing something, a complete stripped down example including:

- create table
- sample data in the form of inserts into statements
- queries you're running

would help a lot!

Static Typing

Badlands, May 24, 2019 - 11:42 am UTC

Thank you for the prompt response. I'll go the static typing route as I assume that there is not a way to do what I want to dynamically with a few lines of code.

I apologize for my comment that you did not understand the question, as clearly you did. Big fan!
Connor McDonald
May 27, 2019 - 6:35 am UTC

GLad we could help

dynamic case when expression

ravi, March 19, 2020 - 7:21 am UTC

How to create dynamic case when expression rather than use hard code value like "(1,2)"?

example
select amount,
case
when :p_para in (1, 2) then
' --- display normal column --- '
when :para in (3, 4) then
' --- display normal column --- '
end output_1,

case
when :p_para in (1, 2) then
amount * ' --- display normal column --- '
when :para in (3, 4) then
amount * ' --- display normal column --- '
end output_2,

case
when :p_para in (1, 2) then
(amount * ' --- display normal column --- ') + tax
when :para in (3, 4) then
(amount * ' --- display normal column --- ') + tax
end output_3
from dual
Chris Saxon
March 19, 2020 - 5:16 pm UTC

I'm not quite sure what you're asking. But you can make the values for the in-list bind variables too:

var v1 number;
var v2 number;
select case
         when 1 in ( :v1, :v2 ) then 'Y'
         else 'N'
       end
from   dual;

CASEWHEN1IN(:V1,:V2)THEN'Y'ELSE'N'END   
N    

exec :v1 := 1;
select case
         when 1 in ( :v1, :v2 ) then 'Y'
         else 'N'
       end
from   dual;

CASEWHEN1IN(:V1,:V2)THEN'Y'ELSE'N'END   
Y  

More to Explore

PL/SQL demos

Check out more PL/SQL tutorials on our LiveSQL tool.

PL/SQL docs

PL/SQL reference manual from the Oracle documentation library