【问题标题】:How to write an SQL multi-insert query for primary and secondary tables如何为主表和辅助表编写 SQL 多插入查询
【发布时间】:2019-07-26 16:54:43
【问题描述】:

我有两个表,我想编写一个多插入查询,这样,第一个表中的 PK 会自动作为 fk 插入到另一个表中。

让我们假设以下表模式:

tblParent

ParentID (Primary Key Auto increment)
ParentValue

tblChild

ChildID (Primary Key Auto increment)
FkParentID (Foreign Key)
ChildValue

现在我想编写一个多插入查询,如下所示

INSERT INTO tblParent, tblChild (ParentValue, FkParentID, ChildValue) VALUES ('Parent 1', <ParentID of 'Parent 1'>, 'Child 1'), ('Parent 2', <ParentID of 'Parent 2'>, 'Child 2'), ('Parent 3', <ParentID of 'Parent 3'>, 'Child 3')

但我不知道该怎么做。 我有数百万条记录要插入这些表中。而且我不想在第一个表中插入记录,然后获取父 ID 并在第二个表中插入记录。

编辑1:我的数据库是Mysql InnoDb

编辑 2:有问题的表具有一对多的关系。所以这意味着我想在 tblParent 中执行一次插入,并为 tblParent 中的每条记录在 tblChild 中执行多次插入

编辑 3:

我正在查看 MySql 文档并遇到以下描述:

https://dev.mysql.com/doc/refman/8.0/en/information-functions.html#function_last-insert-id

当前执行的语句不影响 LAST_INSERT_ID() 的值。假设您使用一条语句生成 AUTO_INCREMENT 值,然后在多行 INSERT 语句中引用 LAST_INSERT_ID(),该语句将行插入到具有自己的 AUTO_INCREMENT 列的表中。 LAST_INSERT_ID() 的值将在第二条语句中保持稳定;它对第二行和后面的行的值不受早期行插入的影响。 (但是,如果您混合对 LAST_INSERT_ID() 和 LAST_INSERT_ID(expr) 的引用,则效果未定义。)

所以我的下一个问题是,LAST_INSERT_ID 在为 tblParent 进行多次插入的情况下会如何表现,而 tblParent 又在 tblChild 中为每个 tblParent 进行多次插入

【问题讨论】:

  • 该帖子stackoverflow.com/questions/4775520/…上的类似问题和可用答案
  • @Xun 感谢您的参考。我的坏我无法正确搜索。如果那里给出的答案令人满意并且适合我的情况,将调查该问题并将其标记为重复。
  • @Xun 我的问题与参考问题的不同之处如下:我必须在我的子表中执行一对多,而参考问题给出了一对一关系的答案.

标签: php mysql foreign-keys


【解决方案1】:
<?php
//your codes

       $inset_tblParent= "INSERT INTO tblParent (ParentValue, FkParentID, ChildValue)VALUES('Parent 1', <ParentID of 'Parent 1'>, 'Child 1')";

     $inset_tblChild= "INSERT INTO tblChild (ParentValue, FkParentID, ChildValue)VALUES('Parent 2', <ParentID of 'Parent 2'>, 'Child 2')";


//your doces            
    ?>

您可以像这样使用多个插入。

【讨论】:

  • 在 tblParent FkParentID 中,ChildValue 不存在。这将如何运作?
  • 你使用 if 条件进行检查
【解决方案2】:

您可以通过以下方式在两个表中插入数据:-

$result = INSERT INTO tblParent (ParentValue) VALUE('ABC');
if($result == true){
    $query = SELECT * tblParent ORDER BY ParentID DESC LIMIT 1;
    $row = $query->fetch_assoc();
    $ParentID = $row['ParentID'];
    INSERT INTO tblChild (FkParentID,ChildValue) VALUE('$ParentID','XYZ');
}

【讨论】:

  • 问题是我想要批量插入,因为我要插入数百万条记录。我不能做单独的插入。这将需要很多时间。你提到的解决方案对我的用例来说效率很低。
  • 你哪个表有百万条记录,你要在哪个表插入数据?
  • 父表将有数百万条记录,而子表将有(父表中的记录数)*10
【解决方案3】:

无论如何,现在我所做的是使用 multi_query 插入值。

我在 while 循环中做了以下操作:

$autoIncForParent = <Max ID from tblParent>;
while(<condition to evaluate>) {
    if (!empty($multiQuery)) {
        $multiQuery .= ";";
    }
    $multiQuery .= "INSERT INTO tblParent (ParentID , ParentValue) VALUES ($autoIncForParent, 'Parent 1');";
    $multiQuery .= "INSERT INTO tblChild (FkParentID , ChildValue) VALUES ($autoIncForParent, 'Child 1');";
$autoIncForParent++;
}
$mysqli->multi_query($multiQuery);

我很确定一定有另一种解决这个问题的好方法。

我已经处理了内存问题、竞争条件以及我的实际代码中没有的问题。 此 sn-p 仅用于详细说明。 这个 sn-p 绝不是完美的,我不建议将它用于生产。

编辑 1:添加了缺少的分号。万一有人提到这个

【讨论】:

  • 出于安全/稳定性原因,我不推荐此答案。使用准备好的语句。
猜你喜欢
  • 2015-05-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多