tags:

views:

535

answers:

4

Consider the query (it runs on both Oracle and MySQL)

UPDATE table1
SET something_id = CASE 
  WHEN table1_id = 1446 THEN 423 
  WHEN table1_id = 2372 THEN 426 
  WHEN table1_id = 2402 THEN 428 
  WHEN table1_id = 2637 THEN 429 
  WHEN table1_id = 2859 THEN 430 
  WHEN table1_id = 3659 THEN 433 
END 
WHERE table1_id IN (1446,2372,2402,2637,2859,3659)

This query can get quite large, so I was wondering what is the limit on the number of conditions (WHEN, THEN statements) a single query can hold. Is there a way around it?

For example:
I know that the max number of values that can be passed to IN is 1000 and to overcome this we can do

`WHERE TABLE1_ID IN ([1000 values]) OR TABLE1_ID IN ([more values])`
A: 

In MySQL you are limited solely by the byte size of the query. This is controlled by the "max_allowed_packet" setting for your server. I cannot speak for Oracle.

hobodave
Not even an upvote? I answered pertaining to MySQL :-(
hobodave
+8  A: 

Put your correspondences into a helper table:

id   value

1446  423
2372  426 
…

and join.

In Oracle:

UPDATE  (
        SELECT  something_id, value
        FROM    table1
        JOIN    helper
        ON      table1.table1_id = helper.id
        )
SET     something_id = value

(don't forget to make helper.id a PRIMARY KEY for this to work)

In MySQL:

UPDATE  table1
JOIN    helper
ON      table1.table1 = helper.id
SET     table1.something_id = value
Quassnoi
You beat me by 26 seconds... Sometimes I wonder how you do that.
Welbog
@Welbog: I just have `SQL` statements bound to the keys, like on old `Spectrum` `BASIC`. Of course I need to remove extra symbols from `QUERY UPDATE APPLY SELECT SELECT NOT OR INSERT` to get my nick, but that's the price one has to pay.
Quassnoi
@Quassnoi: NOT INSERT CURSOR EXECUTE!
Welbog
@Welbog: You have a `CURSOR` bound???!!!
Quassnoi
@Quassnoi: I have it bound so that I can quickly say "NOT CURSOR! NOT CURSOR!"
Welbog
DCookie
+5  A: 

If you have a lot of case statements like this, you should move them into a table to simplify things:

NewTable
table1_id  | result
-----------+---------
1446       | 423
2372       | 426
...        | ...

Then join on it in your query:

UPDATE table1
SET something_id = NewTable.result
INNER JOIN NewTable
ON table1.table1_id = NewTable.table1_id

It's a lot simpler.

Welbog
Nice as it might be, I don't think this UPDATE syntax works in Oracle.
DCookie
+5  A: 

The docs for 10gR2 say:

The maximum number of arguments in a CASE expression is 255. All expressions count toward this limit, including the initial expression of a simple CASE expression and the optional ELSE expression. Each WHEN ... THEN pair counts as two arguments. To avoid exceeding this limit, you can nest CASE expressions so that the return_expr itself is a CASE expression.

skaffman