tags:

views:

138

answers:

4

If I want to update a column value base on a condition I can just use the below query for a simpel +1 -1 case (translate into proper PHP call or ORM equivalent, of course):

UPDATE articles SET STATUS = 0 WHERE STATUS  = 1;

But now the issue is that I want, based on the original the status, infer a new value of status from a dictionary. Assuming that the dictionary is something like this:

dict['1']='3'
dict['12']='2'
dict['6']='2'

There is no relationship between key-value pair. The dict is a PHP dictionary object, that's what I meant by "in memory dictionary".

How to write this query?

Edit: Question edit. I didn't frame the question properly... sorry!

+1  A: 

Use subquery:

UPDATE articles AR SET status = (SELECT value FROM dict WHERE key = AR.status)

Of course, I assume that you have dictionary stored in your database.

samuil
Good try, but that dict is not a database table-- it's an memory-dictionary
Ngu Soon Hui
If it was a table, this could be done with a join instead of a sub-query, which is significantly less taxing on the server.
rwmnau
@rwmnau: Good point ;)@Ngu Soon Hui: what do you mean by memory-dictionary?
samuil
+1  A: 

How about something like this:

UPDATE articles
   SET status = n.new
  FROM articles a
  JOIN NewStatus n
    ON a.status = n.status

That way, you'd have a second table called "NewStatus" that had two columns - one called "status" with your existing status, and one called "New" that had the status you wanted it to update to. Join to that table, do your update, and that should solve it. Also, if there are any statuses you don't want to update, just don't include them in your NewStatus table - then they'll be skipped in the update statement.

It looks like the question's been modified, so if I'm missing the point, please let me know!

rwmnau
+3  A: 

If you have a small number of mappings then you could use a case statement.

BEGIN TRAN

UPDATE articles
SET status = 
       case 
          when status=1 then 3 
          when status=12 or status=6 then 2 
          else status --leave it unchanged if it doesn't match a case
       end

--COMMIT OR ROLLBACK

Otherwise take the mapping table approach as suggested by rwmnau

pjp
This was my initial thought, but I couldn't tell how big the table was from his example. If it's a one-time thing and the table is a manageable size, this might be the easiest way to go.
rwmnau
+1  A: 

Since your question is unclear and you appear to be mixing code and SQL you could do something like this (pseudo Java):

StringBuilder sb = new StringBulder();

for (Map.Entry<Integer,Integer> entry : codes.entrySet) {

    sb.append(
      String.format("UPDATE articles SET Status=%s WHERE Status=%s\n", entry.getValue(), entry.getKey() 
       );

}

String sqlToExecute = sb.toString();
System.out.println(sqlToExecute);

This will give you the SQL to execute to make the changes. If this code is going to be more of a one off then get rid of the String formatting and use prepared statements instead.

pjp
That's something I want
Ngu Soon Hui