【问题标题】:Run multiple queries where all succeed or all fail在全部成功或全部失败的情况下运行多个查询
【发布时间】:2016-03-23 05:22:09
【问题描述】:

我需要将 2 行更新到 2 个不同的表中,然后将一个新行插入到另一个不同的表中,必须这样做才能使它们全部成功或失败。 (我认为这个词是原子的?)。我进行了一些搜索,但似乎只能找到与对一个表进行多次插入或更新相关的问题。

以下是我需要运行的 3 个查询:

UPDATE submission SET status='a' WHERE idgreg = 119 AND status='p' AND userid = 126;

UPDATE greg SET iscomplete=1 WHERE idgreg = 119;

INSERT INTO completion (idperson, idgreg, datecompleted, idsubmission, mediaid, description, 
privatestatus, contenttype, totalamount)  
SELECT s.idperson, s.idgreg, s.datesubmitted, s.idsubmission, COALESCE(s.youtubeid, s.contentid) AS mediaidid, g.description, g.privatestatus, 
g.contenttype, COALESCE(SUM(amount),0) AS totalamount 
FROM submission s 
INNER JOIN greg g on s.idgreg = g.idgreg 
INNER JOIN contribution c on s.idgreg = c.idgreg 
WHERE s.idsubmission = 36 AND c.ispaid = 1;

【问题讨论】:

    标签: mysql sql-update sql-insert atomic


    【解决方案1】:

    您应该将查询包装在 MySQL 事务 中,以确保它们以原子方式执行。但首先,声明错误处理程序,它将在发生错误时ROLLBACK 进行所有更改:

    CREATE PROCEDURE runYourQueries()
    
    BEGIN
    
    DECLARE EXIT HANDLER FOR SQLEXCEPTION ROLLBACK;
    DECLARE EXIT HANDLER FOR SQLWARNING ROLLBACK;
    
    START TRANSACTION;
    
    UPDATE submission SET status='a' WHERE idgreg = 119 AND status='p' AND userid = 126;
    
    UPDATE greg SET iscomplete=1 WHERE idgreg = 119;
    
    INSERT INTO completion (idperson, idgreg, datecompleted, idsubmission, mediaid, description,
        privatestatus, contenttype, totalamount)  
    SELECT s.idperson, s.idgreg, s.datesubmitted, s.idsubmission,
        COALESCE(s.youtubeid, s.contentid) AS mediaidid, g.description, g.privatestatus,
        g.contenttype, COALESCE(SUM(amount),0) AS totalamount 
    FROM submission s 
    INNER JOIN greg g on s.idgreg = g.idgreg 
    INNER JOIN contribution c on s.idgreg = c.idgreg 
    WHERE s.idsubmission = 36 AND c.ispaid = 1;
    
    COMMIT;
    
    END
    

    【讨论】:

    • 这不起作用。我故意让其中一个失败,而其他 2 个查询仍在更新。我在主要问题中添加了一张图片以显示发生了什么。有什么想法吗?
    • 您必须选择一个 事务性 引擎,例如 InnoDb。请参阅文档dev.mysql.com/doc/refman/5.0/en/ansi-diff-transactions.html
    • @Mitchell 您应该使用存储过程来利用ROLLBACK,这将在发生错误时撤消所有操作。
    • 我正在使用 InnoDB。好的,现在就来看看,当我让它工作或不工作时会回来
    • 在定义过程之前,我收到了 DECLARES 错误。但是,如果我把 DECLARES 放在 BEGIN 之后,我什么也得不到。这是正确的吗?
    猜你喜欢
    • 2021-09-13
    • 2016-04-18
    • 1970-01-01
    • 2023-03-28
    • 2017-03-28
    • 2019-05-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多