Question

I'm trying to run multiple update statements within a MySQL transaction, but I need the WHERE clauses in each to reference the values existing before the start of the transaction. (Using innoDB table.)

For example, I have the following table of flights (simplified, obviously):

flight  aircraft     dep_time
1       1            05:00
2       1            06:00
3       1            07:00

4       2            05:00
5       2            06:00
6       2            07:00

What I need to be able to do is swap flights on aircraft 1 departing 06:00 or later with flights on aircraft 2 departing at 06:00 or later. I currently do this by assigning an intermediate aircraft to each flight, then updating the flights with this intermediate aircraft to the desired aircraft. For example:

UPDATE flights SET aircraft = 1001 WHERE aircraft = 1 AND dep_time >= 06:00
UPDATE flights SET aircraft = 1002 WHERE aircraft = 2 AND dep_time >= 06:00
UPDATE flights SET aircraft = 2 WHERE aircraft = 1001
UPDATE flights SET aircraft = 1 WHERE aircraft = 1002

It seems like I could avoid the two additional update statements by using a transaction. Additionally, the method I'm using now would cause a major problem if there was actually an aircraft 1001 in the database (I'm just using a very large number at this point to make sure this doesn't occur) ... something I'd like to avoid. My intent is to do something like this:

START TRANSACTION();
UPDATE flights SET aircraft = 2 WHERE aircraft = 1 AND dep_time >= 06:00
UPDATE flights SET aircraft = 1 WHERE aircraft = 2 AND dep_time >= 06:00
COMMIT();

As I understand it, the second update statement will see the values that were updated in the first statement, which will mess everything up. Is there a way I can make both UPDATE statements use the values that existed when the transaction was started? If not, does anyone have a better suggestion on how to handle this?

My desired outcome is this:

flight  aircraft     dep_time
1       1            05:00
2       2            06:00
3       2            07:00

4       2            05:00
5       1            06:00
6       1            07:00

Thank you! I apologize if this isn't clear...

No correct solution

OTHER TIPS

You need to add unique column to your table (usually it will have name id and to be unsigned big int auto_increment type)

Then you will be able to swap rows as you wish, as soon as each row will have unique id.

This isn't really about transactions at all, it's about using UPDATE to swap values (whether inside a single transaction or not). Transactions don't "save the data that exists at the start of the transaction" the way your question implies: You seem to be misunderstanding what they're for. You can COMMIT or ROLLBACK an in-progress transaction, but you can't write queries that refer explicitly to current vs. pre-transaction DB data.

If you need to "save" the data at a given point in time, you could copy it to a temporary table, or to another column that you creat in your current table just for this (temporary storage) purpose.

However, a simpler solution is this: If you can write the entire thing as a single update statement, then you won't have a problem, since each row will only be processed once by a single UPDATE, e.g.:

UPDATE flights SET aircraft = IF(aircraft=1,2,1) WHERE (aircraft = 1 OR aircraft = 2) AND dep_time >= 06:00

should solve your problem in this particular case.

(That said, bear in mind that if you are updating a primary or unique key, the rows are still updated one-by-one and this can cause duplicate key errors, even if the final result of the update wouldn't have any. So in such cases you may have to either order the update carefully using ORDER BY, or else you might have to temporarily insert dummy values and use multiple UPDATE statements, the way you're currently doing it.)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top