Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to tell if a mysql insert is successful

Tags:

mysql

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:

  1. Begin the transaction
  2. Update Table1
  3. Insert into Table2
  4. If Insert is successful, a. then insert into Table3 and commit. b. else rollback the transaction.

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;
like image 541
Code Dragon Avatar asked Oct 22 '22 13:10

Code Dragon


2 Answers

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.

like image 68
fancyPants Avatar answered Oct 24 '22 07:10

fancyPants


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.

like image 34
Brandon Buck Avatar answered Oct 24 '22 07:10

Brandon Buck