tags:

views:

79

answers:

4

I want to update a record in a table but based on a condition I will either update one column or another but I do not want to have 2 separate statements because the statements are very long and detailed.

Here is the basic idea with over simplification to get to the point.

PROCEDURE Animal_something(p_updater VARCHAR2)

begin

  if p_updater = 'person' then   
    -- I want to update the modified_by  
  else   
    -- if p_updater = 'a process' I want to update modified_by_process

Update table_creatures
   set animal_type = 'Dog ,

**modified_by** = 'Bob'   
**or do this**  
**modified_by_process =** 'creature_package'

 where animal_legs = '4'

I don't want:

if p_updater = 'person' then 
  Update table_creatures   
     set animal_type = 'Dog ,  
         modified_by = 'Bob'  
   where animal_legs = '4';  
else  

  Update table_creatures  
     set animal_type = 'Dog , 
         modified_by_process = 'creature_package'  
   where animal_legs = '4';

end;
+2  A: 
UPDATE  table_creatures
SET     animal_type = 'Dog',
        modified_by = CASE p_updater WHEN 'person' THEN 'Bob' ELSE modified_by END,
        modified_by_process = CASE p_updater WHEN 'process' THEN 'creature_package' ELSE modified_by_process END
WHERE   animal_legs = 4
Quassnoi
+1, beat me to it :)
Peter Lang
A: 

You could use dynamic SQL, e.g.:

PROCEDURE Animal_something(p_updater VARCHAR2)

  sql_string_pt1  VARCHAR2(2000) := 'UPDATE table_creatures SET animal_type = :1';
  sql_string_pt2  VARCHAR2(2000) := NULL;
  sql_string_pt3  VARCHAR2(2000) := ' WHERE animal_legs = :3';

begin

  if p_updater = 'person' then   
    sql_string_pt2 := ', modified_by = :2';
  else
    sql_string_pt2 := ', modified_by_process = :2';
  end if;

  EXECUTE IMMEDIATE sql_string_pt1 || sql_string_pt2 || sql_string_pt3
    USING 'Dog', 'Bob', '4';

end;

This has two advantages over Quassnoi's answer: use of bind variables, and not needing to update both columns on every execution, which would generate redo even though the actual value is not changed.

On the downside, the statement is not validated at all at compile time.

Dave Costa
Huh? Literals are literals, they don't need to be "BOUND". By their very nature they WILL NOT CHANGE from execution to execution. And I'm pretty sure he meant for anything which will change to be changed to a variable in z-dan's code, and it will be validated.
Stephanie Page
I've never used anything like this, very cool approach, I might try this out. Although, I'm wondering with a long update statement if it's the best way to code from a maintenance perspective.
z-dan
@Page: you're probably right, but I'd lean towards Costa's approach, i.e. if the questioner asks a question like this, chances are they don't know the difference between using literals and bind variables, so it's a good idea to illustrate best practice. 'Dog', 'Bob' and '4' seem like good candidates for variables.@z-dan: dynamic SQL is a compromise between flexibility and maintainability, although there are ways to make it easier to spot errors (e.g. using a pattern with token replacements instead of concatenating different parts of the SQL together bit by bit).
Jeffrey Kemp
A: 
UPDATE  table_creatures 
SET     animal_type = 'Dog', 
        modified_by = DECODE(p_updater , 'person' , 'BOB' , 
                                         'proces' , 'creature_package' ,
                                         'GIVE DEFAULT VALUE')          
WHERE   animal_legs = 4;

You can try this.

Bharat
He wants to update a different *column* based on the value of `p_updater`, not just update `modified_by` with a different value.
Dave Costa
If p_updater is a column in table_creatures, then above query will work.This query was updating modified_by based on p_updater value
Bharat
A: 

.............................

z-dan