【问题标题】:Cakephp 3.0 bulk insertCakephp 3.0 批量插入
【发布时间】:2023-03-06 10:24:01
【问题描述】:

在 Cakephp 3.0 中,为了保存许多记录,指示使用saveMany 函数。

https://book.cakephp.org/3.0/en/orm/saving-data.html#saving-multiple-entities

不过,上面的提交插入语句一个接一个

我需要一次更新几千条记录,所以我想批量插入我的记录,而不是一条一条地插入。

为了验证这一点,我尝试了saveMany 的行为,我检查了我的querys.log,似乎使用saveMany 不会批量插入我的查询,而是一个接一个地插入。

换句话说,我想要这个:

INSERT INTO mytable (id, code) VALUES ('123', 'code_a'), ('123', 'code_b'), ('123', 'code_c'), ('123', 'code_d'), ('123', 'code_e');

但是执行了以下操作

INSERT INTO mytable (id, code) VALUES ('123', 'code_a')
INSERT INTO mytable (id, code) VALUES ('123', 'code_b')
INSERT INTO mytable (id, code) VALUES ('123', 'code_c')
INSERT INTO mytable (id, code) VALUES ('123', 'code_d')
INSERT INTO mytable (id, code) VALUES ('123', 'code_e')

所以我的问题是,如何在 Cakephp 3.0

中进行 批量插入

注意:我做了一些研究,发现saveAll 函数在 Cakephp 2.0 中,它可以进行批处理(据说),但遗憾的是,3.0 中没有这样的函数。 p>

【问题讨论】:

标签: cakephp


【解决方案1】:

cakephp 中的批量插入非常简单:

<?php 

$query = $this->MyModel->query(); 

foreach ($data as $row) {
    $query
        ->insert(['column1', 'column2'])
        ->values([
            'column1' => $row['value1'], 
            'column2' => $row['value2']
        ]);
}

$query->execute();

【讨论】:

  • 如何一次将所有 id 获取到相应的插入?
【解决方案2】:
$mytable = TableRegistry::getTableLocator()->get('ModelNameOfTable');

foreach ($myEntitys as $row)
{
    $record = $mytable->newEntity();

    foreach ($row as $column => $value)
    {
        $record->{$column} = $value;
    }

    if ($mytable->save($record))
    {
        $id = $record->id; // for checking if needed
    }
}

应该这样做。

仅供参考:https://book.cakephp.org/3.0/en/orm/saving-data.html

尽管如此,如果您的表非常复杂,并且您需要进行大量交叉引用/字段检查,那么像您一样创建自己的自定义 SQL 执行可能更合适。

使用 ORM 和模型的理想是保持代码在不同的数据库平台(模型)之间共享。在您的情况下,您正在编写一些东西来“传输”数据而不是共享。

【讨论】:

  • 我想要实现的关键点是创建 SQLINSERT INTO mytable (id, code) VALUES ('123', 'code_a'), ('123', 'code_b'), ('123', 'code_c'), ('123', 'code_d'), ('123', 'code_e');,我非常怀疑这种方法能否解决它。不过有时间我会试试的,谢谢!
  • you are writing something to "transfer" data 是的,这正是我的逻辑正在做的事情。我需要从数据库中获取大量数据,处理,然后将它们插入另一个数据库,在批量插入之前已经完成了验证。谢谢。
【解决方案3】:
  • 当您使用 INSERT INTO mytable (id, code) VALUES ('123', 'code_a'), ('123', 'code_b'), ('123', 'code_c'), ('123', 'code_d'), ('123', 'code_e'); 进行“批量”插入时,您会在一个 sql 查询中发送所有插入数据而无需验证,但 db 本身会在后台一一插入。
  • 在 ORM 中,您的应用首先进行数据验证,然后为当前实体创建 sql 查询。速度差别不大。

【讨论】:

  • 感谢您的输入,但在我的测试中,实际上速度差异很大,在我从使用下面的答案切换后,我的查询速度从30s 提高到5s
【解决方案4】:

因为我真的需要批量插入,我现在需要使用传统的执行来处理我的查询:

<?php
    $sql = "INSERT INTO mytable ";
    $binding = [];
    $insertSql = [];
    foreach($myEntitys as $i => $myEntity){
        $myEntityArray = $myEntity->toArray();
        $myEntityArrayKeys = array_keys($myEntityArray);

        if($i === 0){
            $sql .= "(";
            $sql .= implode(",", $myEntityArrayKeys);
            $sql .= ")";
        }

        $singleInsertSql = [];
        foreach($myEntityArrayKeys as $key) {
            $value = $myEntityArray[$key];
             $singleInsertSql[] = "?";
             $binding[] = $value;
        }
        $insertSql[] = "(" . implode(",", $singleInsertSql) . ")";
    }
    $sql .= " VALUES " . implode(",", $insertSql);

    $connection = ConnectionManager::get('default');
    $connection->execute($sql, $binding);

这个可以做但是很丑,希望有人可以发布一个更蛋糕原生的方法,谢谢!

【讨论】:

    猜你喜欢
    • 2016-05-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-15
    • 1970-01-01
    • 2015-03-28
    相关资源
    最近更新 更多