【问题标题】:Is there a way to test a mysql insert or update prior to actually inserting or updating?有没有办法在实际插入或更新之前测试 mysql 插入或更新?
【发布时间】:2014-02-23 12:45:31
【问题描述】:

我的 PHP/Mysql 脚本分阶段工作:

Insert Customer info
  Get new customer's ID via mysqli_insert_id(blah)
Insert into ADDRESS using new customer's ID
Insert into PHONE using new customer's ID
Insert into CONTACTS using new customer's ID

我的问题是:如果后面的插入语句之一出现问题,MYSQL 会停止并当然会抛出错误,但最初的 Customer INSERT 已经触发并成功。现在,如果我们返回并更正输入中的错误并尝试再次执行此操作,我们将获得该客户的多个部分条目。

所以问题:有没有办法测试所有 MySQL 插入是否有错误,如果没有发现,那么继续提交所有错误?

例如:

Insert Customer info (check for would-be errors; don't actually insert)
  Get new customer's ID...
Insert into ADDRESS...(check for would-be errors; don't actually insert)
Insert into PHONE...(check for would-be errors; don't actually insert)
Insert into CONTACTS...(check for would-be errors; don't actually insert)

好的,既然没有抛出错误并且实际上没有插入任何内容,请执行所有预先筛选的插入!

这存在吗?

【问题讨论】:

标签: php mysql insert


【解决方案1】:

使用 MySQL 事务。

事务是一组顺序的数据库操作操作,它的执行就像它是一个单独的工作单元一样。换句话说,除非组内的每个单独操作都成功,否则事务将永远不会完成。如果事务中的任何操作失败,则整个事务都会失败。

实际上,您会将许多 SQL 查询组合到一个组中,并将所有这些查询作为事务的一部分一起执行。

阅读有关MySQL transaction的教程

【讨论】:

    【解决方案2】:

    是的,事务允许您执行一系列查询,并在最后提交所有这些更改,或者在其中一个查询失败时回滚它们。
    如果您使用的是 PDO,则基本设置如下:

    //optional
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    try
    {
        $pdo->beginTransaction();
        $stmt = $pdo->prepare();
        $pdo->query();
        //in short, all your queries here
        $pdo->commit();//commit changes to DB
    }
    catch (PDOException $e)
    {
        $pdo->rollBack();//Nothing is changed in DB
    }
    

    当然,事务在事务安全 存储引擎(InnoDB、BerkeleyDB、ndbcluster)上效果最好。从 MySQL 5 开始,事务确实在 MyISAM 上工作,但为了使它们是原子的,因此可以安全使用,您必须自己锁定和解锁表。
    the mysql docs for more details

    【讨论】:

    • 我觉得必须要注意的是MyISAM表不支持事务;只有 InnoDB 表支持它们。
    • @Barranka:嗯,InnoDB、ndbcluster 和大多数现代存储引擎都支持事务......我会对此添加一个注释,但我认为大多数人应该知道应该避免使用 MyISAM 99仍然有 % 的时间
    • hehehe 为什么对 MyISAM 有仇恨?它快速(非常快)且稳定......它有效......在某些情况下,MyISAM 是最佳选择。但是,如果(例如)需要事务支持,我同意,不能使用它。
    • @Barranka:MyISAM 存在根本缺陷,它不支持外键约束。这意味着如果您使用 MyISAM,则无需关心数据完整性。插入时引擎也不会锁定行级别,而是锁定表。所以可以肯定的是,对于简单的选择查询,它可能会更快,但是当您开始定期插入时,InnoDB 会毫不犹豫地击败它。说真的,更新 1 行中的 1 个字段,MyISAM 会阻塞整个表!最后,InnoDB 有一个弱点:缺乏全文搜索,但这是 MySQL 5.5+ 中添加的一项功能(尽管需要一些工作)
    【解决方案3】:

    事务最适合回滚状态。 ifthats not possible 用 insert 为语句添加前缀,它应该让您知道任何错误

    【讨论】:

      【解决方案4】:

      这是一个使用 mysqli 来支持我的评论的示例:

      if (isset($_POST) && isset($_POST['whatever']))
      {
      
          $con = new mysqli("localhost", "user", "pw", "db");
          // begin transaction by setting autocommit to false;
          $con->autocommit(FALSE);
      
          $stmt = $con->prepare("INSERT INTO `something` (`data`) VALUES (?)");
          $stmt->bind_param("s", $_POST['whatever']);
          $stmt->execute();
          if (!$stmt)
          {
              $con->rollback();
          }
          else
          {
              $con->commit();
          }
      
          $stmt->close();
      }
      

      您应该知道事务需要 innodb 表。它有助于检查规格: http://dev.mysql.com/doc/refman/5.0/en/commit.html

      查看巴兰卡的 cmets 了解更多详情

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-03-06
        • 2015-04-25
        • 1970-01-01
        • 2021-08-22
        • 2015-11-21
        • 1970-01-01
        相关资源
        最近更新 更多