ThinkPHP6 批量新增saveAll() 的鬼

  • 后端
  • 2022-03-14
  • 2242 已阅读
  • 作者: huwhois
  • 来源:
       
简介ThinkPHP6 在批量插入saveAll() 的是循环调用create()方法, 如果需要提交大量数据, 还是自己拼sql 比较快

ThinkPHP6 在批量插入saveAll() 的是循环调用save()方法, 如果需要提交大量数据, 还是自己拼sql 比较快.

  1. 源码位置 topthink/think-orm/src/Model.php 757行

     /**
      * 保存多个数据到当前数据对象
      * @access public
      * @param iterable $dataSet 数据
      * @param boolean  $replace 是否自动识别更新和写入
      * @return Collection
      * @throws \Exception
      */
     public function saveAll(iterable $dataSet, bool $replace = true): Collection
     {
         $db = $this->db();
    
         $result = $db->transaction(function () use ($replace, $dataSet) {
    
             $pk = $this->getPk();
    
             if (is_string($pk) && $replace) {
                 $auto = true;
             }
    
             $result = [];
    
             $suffix = $this->getSuffix();
    
             foreach ($dataSet as $key => $data) {
                 if ($this->exists || (!empty($auto) && isset($data[$pk]))) {
                     $result[$key] = static::update($data, [], [], $suffix);
                 } else {
                     $result[$key] = static::create($data, $this->field, $this->replace, $suffix);
                 }
             }
    
             return $result;
         });
    
         return $this->toCollection($result);
     }

    可以看到, saveAll 循环数据集后根据数据情况分别调用 create() 和 update 方法, 这么做的好处是可以一起完成更新和新增.

所以当批量数据写入(一般是导入处理)时建议手动拼写sql

    public static function createMultiple(array $data)
    {
        $sql = "INSERT INTO `data`(`id`,`num`,`title`,`content`)  VALUES ";
        foreach ($data as $value) {
            $sql .= "('" . $value['id'] . "','" .  $value['num'] . "','" . $value['title'] . "','" . $value['content'] . "'),";
        }
        $sql = rtrim($sql, ',');

        Db::execute($sql);
    }

另: mysql 批量写入有大小限制, 注意分开批量, 可以使用 array_chunk 处理数组, 或嵌套循环多次批量插入

很赞哦! ( 1 )