简体   繁体   中英

MySQL: insert, update and check in a single query

I'm hosting a website where the content can be added by authorized users. The content is placed within blocks on the webpage. Authorized users are able to create new blocks and to put the blocks in a specific order. The order and content of the blocks are stored within a database.

When new blocks are created the following two MySQL queries are executed:

The order number, of the blocks within the database, are updated with the following query:

UPDATE `Block`
SET `block_order` = `block_order` + 1
WHERE `tab_nr` = $tab_nr
AND `block_order` > $nr;

The new block is added by executing the following query:

INSERT INTO `Block`
  (`id`, `tab_nr`, `block_order`, `html`, `created`)
VALUES
  (NULL, $tab_nr, $nr + 1, '$html', CURRENT_TIMESTAMP);

The problem with those queries is that the first query is executed no matter what happens with the second query. If the second query fails (whatever the reason may be) the order number of the other blocks were still changed by the execution of the first query. This way the block order numbers got messed up.

What I need is a single query that adds the new block to the database and updates the order numbers of the other blocks if and only if there are equally numbered blocks. The problem though is that I couldn't find a query that does everything I need. For example "ON DUPLICATE KEY UPDATE" will only update the row that conflicts with the new insert, but in my case other rows need to be updated too. Are there any suggestions for a query that get rid of the above mentioned problems?

Take a look at transactional database queries . This is the proper way to accomplish what you're trying to do.

You need to use transaction query, as Matt said in his comment. Something like this can be helpful.

START TRANSACTION;

UPDATE Block
SET block_order = block_order + 1
WHERE tab_nr = $tab_nr
AND block_order > $nr;

INSERT INTO Block
  (id, tab_nr, block_order, html, created)
VALUES
  (NULL, $tab_nr, $nr + 1, '$html', CURRENT_TIMESTAMP);

COMMIT;

So, even if the first query fails, the whole transaction will rollback and save you the mess.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM