【问题标题】:Multiple Insert in one transaction mysqli php5一个事务中的多个插入mysqli php5
【发布时间】:2014-09-19 11:58:57
【问题描述】:

我有 3 张桌子: 用户、学生、学生详情

用户的主键是表student (userid) 中字段的外键,学生的主键是表studentdetails (studentid) 中字段的外键。

我需要在一次提交中将数据从一个表单插入到所有 3 个表中,以下是 SQL 脚本:

    $sql = "

    INSERT INTO `tbluser`(`username`, `password`, `roleid`, `datecreated`)
    VALUES ('$email','$password', '$role', CURRENT_TIMESTAMP);

    SELECT @uid := MAX(`userid`) FROM `tbluser`;

    INSERT INTO `tblstudent` (`userid`, `scholarnumber`, `firstname`, `middlename`,
    `lastname`, `datecreated`)
    VALUES ('@uid', '$scholar_no', '$first_name', '$middle_name', '$last_name',
    CURRENT_TIMESTAMP);


    SELECT @stuID :=  MAX(`studentid`) FROM `tblstudent`;

    INSERT INTO `tblstudentdetails` (`studentid`,`dob`, `studenttype`, `gender`,
    `religion`, `category`, `currentsuburbid`,   `currentcityid`, `currentaddress1`,
    `currentzipcode`, `currentstateid`,  `currentcountryid`,`mobile`,`phone1`,`email1`,
    `passportnum`, `permasuburbid`,  `permaaddress1`, `dateofjoining`,
    `admissionreferenceof`, `datecreated`, `dateupdated`) 

    VALUES ('@stuid', '$dob' ,'$studenttype' ,'$gender','$religion','$category',
    '$currentsuburbid', ' $currentcityid', '$currentaddress1', '$currentzipcode',
    '$currentstateid', '$currentcountryid', '$mobile',
    '$phone1','$email1','$passportnum','$permanentsuburbid', '$permanentaddress1',
    '$doj', ' $admissionreference',current_timestamp, current_timestamp);

    ";

我无法找出问题所在,上面的脚本在 mysql (phpmyadmin) 中工作,但在 php 中它不起作用。我了解,我需要使用我的 multi_query (??),但它不会给出任何错误并插入两个表,但不会插入第三个表。我觉得这可能与两者之间的 SELECT 语句有关?在这里斗智斗勇,我将不胜感激任何帮助。提前致谢。

【问题讨论】:

  • 尝试执行多个 SQL 语句不是一个好主意。将语句拆分为多个插入并分别执行。
  • 我会做单独的 SQL 语句只是为了能够有更多的控制和错误处理。但是,如果您觉得必须一次性完成所有这些数据库工作,请创建一个存储过程来完成所有这些工作。

标签: mysql php-5.5 mysqli-multi-query


【解决方案1】:

您似乎正试图从 mysqli 运行多个用分号分隔的 SQL 语句。那是行不通的。您需要分别发出每个不同的语句。

您可以使用 MySQL 的事务(只要您对表使用 InnoDB 或其他一些访问方法,并且 MyISAM:MyISAM 不处理事务)。

你可以这样做:

$connection->begin_transaction();
/* issue your statements one by one */
$connection->commit();

这将使您的所有插入等内容同时可见。

但是:您正在尝试使用您最近的自动增量 ID 号。你这样做是错误的。你需要使用 MySQL 的 LAST_INSERT_ID() 函数来代替你的

SELECT @uid := MAX(`userid`) FROM `tbluser`;   /*wrong*/

模式。这是有效的,因为LAST_INSERT_ID() 从您的第一个插入中传递了 ID 的值,因此第二个插入将使用它。即使多个程序向表中插入内容也是安全的,因为 MySQL 为每个程序连接保留一个单独的值。它比您拥有的更快,因为它不必查看表格,并在使用之前将值返回给您的程序。

这样做,你会得到你想要的。

/* do the first insert, using an autoincrementing uid column */
INSERT INTO `tbluser`(whatever, whatever, whatever)
              VALUES (whatever, whatever, whatever);
/* now LAST_INSERT_ID() contains the value inserted into tbluser.uid */

/* do the second insert, using the id from the first insert into tblstudent.userid */
INSERT INTO `tblstudent` (`userid`,         whatever, whatever, whatever)
                  VALUES (LAST_INSERT_ID(), whatever, whatever, whatever);
/* now LAST_INSERT_ID() contains the value inserted into tblstudend.studentid */

/* use that value to insert into tblstudentdetails.studentid */
INSERT INTO `tblstudentdetails` (`studentid`,      whatever, whatever, whatever) 
                         VALUES (LAST_INSERT_ID(), whatever, whatever, whatever);

【讨论】:

  • 谢谢。我正在使用 InnoDB 并且我正在使用 last_insert_ID() 但在某处读到它可能并不总是有效,但是,我现在已经改变了它。另外,正如 Gordan & Ed 所建议的,我可以问一下,使用 multi_query 是否是个坏主意?我可以将代码更改为每次发送一个 sql,但认为让 mysql 一次性完成工作并将确认发送到 php 更好?非常感谢您的帮助,再次感谢您!
  • LAST_INSERT_ID() 非常可靠,只要您不编辑代码以在依赖于它的语句之间滑动更多 INSERT 语句。如果您愿意,可以使用multi_query。但该 API 中没有内置的事务控制。
猜你喜欢
  • 2020-08-13
  • 2011-01-08
  • 1970-01-01
  • 2012-11-20
  • 1970-01-01
  • 2016-05-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多