I'm learning MySQL transactions. I've searched for answers to this, but they all seem to use PHP to make what I want to do work. Here's the example of what I'm trying to do:
I don't understand how to determine programmatically whether the insert at step 3 was successful. Sure, I can query the table and see, but I thought there was some way to use the return value, but it seems that only works when I'm using PHP to do the transaction.
This is the code block for what I'm trying - it doesn't work:
begin;
start transaction;
-- attempt to reduce inventory
update store_inventory set item_qty = item_qty - 2 where id = 1;
update store_inventory set item_qty = item_qty -1 where id = 5;
-- insert the order record and check whether it succeded
insert into store_orders (purchaser_name, purchase_date)
values ('test user', now());
-- if successful, do final insert and commit
if Row_Count() > 0 Then
insert into store_inventory (order_id, inventory_id, item_qty)
values (1, 1, 2),
(1, 2, 1);
commit;
else -- otherwise rollback
rollback;
end if;
end;
The answer is a mix of Itay Moav-Malimovka and Gordon's answer.
Everything between start transaction
and commit
is one atomic action. Just write it like this:
start transaction;
-- attempt to reduce inventory
update store_inventory set item_qty = item_qty - 2 where id = 1;
update store_inventory set item_qty = item_qty -1 where id = 5;
-- insert the order record
insert into store_orders (purchaser_name, purchase_date)
values ('test user', now());
insert into store_inventory (order_id, inventory_id, item_qty)
values (1, 1, 2),
(1, 2, 1);
commit;
Or let me explain it on an easier example what's going on.
create table foo(id int primary key);
insert into foo values (1);
Now, if you have code like this:
start transaction;
insert into foo values(2);
insert into foo values(1);
insert into foo values(3);
commit;
An error is raised when the value 1
gets inserted because it violates the primary key, an entry with 1
already exists and the code that follows will never be executed. If you do a select * from foo;
now, you will see, that there's a value of 2
in your table. But that's probably just you who sees the 2
in there, that depends on the isolation level (you might want to read about those). This is because the transaction is still pending. Now it's up to you, if you don't care and continue with inserting value 3
and commit or you rollback. BUT this is done on application level. Simply check for an error, if one was raised rollback, if not, everything's fine. There's no need to check inside the transaction, because if anything goes wrong / the insert fails, the code for checking if anything failed will never be reached.
You're probably going to need stored procedures, but I may be wrong on that being a requirement. You'll need to setup transactions yourself and do some testing.
DELIMITER $$
CREATE PROCEDURE `sample`(name VARCHAR(100))
BEGIN
START TRANSACTION; -- Begin a transaction
INSERT INTO `users` (`name`) VALUES name;
IF ROW_COUNT() > 0 THEN -- ROW_COUNT() returns the number of rows updated/inserted/deleted
COMMIT; -- Finalize the transaction
ELSE
ROLLBACK; -- Revert all changes made before the transaction began
END IF
END$$
DELIMITER ;
Something like this may work (this is untested, purely pieced together from research) and you will have to use InnoDB as the storage engine because MyISAM does not support transactions.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With